Author: JaydeepChauhan14 Date: 2024-07-16T09:40:45+08:00 New Revision: bddab518db003f7c5ce9014e9ebd932fb7a85d2f
URL: https://github.com/llvm/llvm-project/commit/bddab518db003f7c5ce9014e9ebd932fb7a85d2f DIFF: https://github.com/llvm/llvm-project/commit/bddab518db003f7c5ce9014e9ebd932fb7a85d2f.diff LOG: [X86][MC,Driver] Support -msse2avx to encode SSE instruction with VEX prefix (#96860) For GCC compatibility https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/x86-Options.html. Added: clang/test/Driver/msse2avx.c llvm/test/MC/AsmParser/sse2avx-att.s Modified: clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Clang.cpp clang/tools/driver/cc1as_main.cpp llvm/include/llvm/MC/MCTargetOptions.h llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h llvm/lib/MC/MCTargetOptionsCommandFlags.cpp llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp llvm/utils/TableGen/X86InstrMappingEmitter.cpp llvm/utils/TableGen/X86ManualInstrMapping.def Removed: ################################################################################ diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index f1ddd2276e816..f671b780bcbeb 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -38,6 +38,7 @@ VALUE_CODEGENOPT(Name, Bits, Default) CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as CODEGENOPT(Crel, 1, 0) ///< -Wa,--crel CODEGENOPT(RelaxELFRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no} +CODEGENOPT(SSE2AVX , 1, 0) ///< -msse2avx CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index be177dc38bcf1..234958f4eb382 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5179,6 +5179,13 @@ def mvx : Flag<["-"], "mvx">, Group<m_Group>; def mno_vx : Flag<["-"], "mno-vx">, Group<m_Group>; } // let Flags = [TargetSpecific] +let Flags = [TargetSpecific] in { +def msse2avx : Flag<["-"], "msse2avx">, Group<m_Group>, + Visibility<[ClangOption, CC1Option, CC1AsOption]>, + HelpText<"Specify that the assembler should encode SSE instructions with VEX prefix">, + MarshallingInfoFlag<CodeGenOpts<"SSE2AVX">>; +} // let Flags = [TargetSpecific] + defm zvector : BoolFOption<"zvector", LangOpts<"ZVector">, DefaultFalse, PosFlag<SetTrue, [], [ClangOption, CC1Option], diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7369887371200..d48b26cc74132 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2545,6 +2545,13 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, switch (C.getDefaultToolChain().getArch()) { default: break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (Value == "-msse2avx") { + CmdArgs.push_back("-msse2avx"); + continue; + } + break; case llvm::Triple::wasm32: case llvm::Triple::wasm64: if (Value == "--no-type-check") { diff --git a/clang/test/Driver/msse2avx.c b/clang/test/Driver/msse2avx.c new file mode 100644 index 0000000000000..37ba6f320fa97 --- /dev/null +++ b/clang/test/Driver/msse2avx.c @@ -0,0 +1,7 @@ +// RUN: %clang -### -c -march=x86-64 -Xassembler -msse2avx %s 2>&1 | FileCheck %s +// RUN: %clang -### -c -march=x86-64 -x assembler -Xassembler -msse2avx %s 2>&1 | FileCheck %s + +// CHECK: "-msse2avx" + +// RUN: not %clang -### -c --target=aarch64 -march=armv8a -msse2avx %s 2>&1 | FileCheck --check-prefix=ERR %s +// ERR: error: unsupported option '-msse2avx' for target 'aarch64' diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 4e0aa1450563e..ec93f092713f5 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -98,6 +98,8 @@ struct AssemblerInvocation { LLVM_PREFERRED_TYPE(bool) unsigned RelaxELFRelocations : 1; LLVM_PREFERRED_TYPE(bool) + unsigned SSE2AVX : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Dwarf64 : 1; unsigned DwarfVersion; std::string DwarfDebugFlags; @@ -197,6 +199,7 @@ struct AssemblerInvocation { ShowInst = 0; ShowEncoding = 0; RelaxAll = 0; + SSE2AVX = 0; NoExecStack = 0; FatalWarnings = 0; NoWarn = 0; @@ -288,6 +291,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, } Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no); + Opts.SSE2AVX = Args.hasArg(OPT_msse2avx); if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32)) Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); @@ -437,6 +441,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels; MCOptions.Crel = Opts.Crel; MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations; + MCOptions.X86Sse2Avx = Opts.SSE2AVX; MCOptions.CompressDebugSections = Opts.CompressDebugSections; MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h index 98317712250bf..899299fd15246 100644 --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -68,6 +68,8 @@ class MCTargetOptions { // ELF. bool X86RelaxRelocations = true; + bool X86Sse2Avx = false; + EmitDwarfUnwindType EmitDwarfUnwind; int DwarfVersion = 0; diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h index c419f2998a383..9d592446f3ba7 100644 --- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -55,6 +55,8 @@ bool getCrel(); bool getX86RelaxRelocations(); +bool getX86Sse2Avx(); + std::string getABIName(); std::string getAsSecureLogFile(); diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp index 42d9b7056e9eb..813b1194b47cb 100644 --- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp +++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp @@ -49,6 +49,7 @@ MCOPT(bool, NoTypeCheck) MCOPT(bool, SaveTempLabels) MCOPT(bool, Crel) MCOPT(bool, X86RelaxRelocations) +MCOPT(bool, X86Sse2Avx) MCOPT(std::string, ABIName) MCOPT(std::string, AsSecureLogFile) @@ -140,6 +141,11 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() { cl::init(true)); MCBINDOPT(X86RelaxRelocations); + static cl::opt<bool> X86Sse2Avx( + "x86-sse2avx", cl::desc("Specify that the assembler should encode SSE " + "instructions with VEX prefix")); + MCBINDOPT(X86Sse2Avx); + static cl::opt<std::string> ABIName( "target-abi", cl::Hidden, cl::desc("The name of the ABI to be targeted from the backend."), @@ -169,6 +175,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() { Options.MCSaveTempLabels = getSaveTempLabels(); Options.Crel = getCrel(); Options.X86RelaxRelocations = getX86RelaxRelocations(); + Options.X86Sse2Avx = getX86Sse2Avx(); Options.EmitDwarfUnwind = getEmitDwarfUnwind(); Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical(); Options.AsSecureLogFile = getAsSecureLogFile(); diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index daf982322bce9..c7f88fed9b128 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -58,6 +58,10 @@ static bool checkScale(unsigned Scale, StringRef &ErrMsg) { namespace { +// Including the generated SSE2AVX compression tables. +#define GET_X86_SSE2AVX_TABLE +#include "X86GenInstrMapping.inc" + static const char OpPrecedence[] = { 0, // IC_OR 1, // IC_XOR @@ -3744,7 +3748,27 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return false; } +static bool convertSSEToAVX(MCInst &Inst) { + ArrayRef<X86TableEntry> Table{X86SSE2AVXTable}; + unsigned Opcode = Inst.getOpcode(); + const auto I = llvm::lower_bound(Table, Opcode); + if (I == Table.end() || I->OldOpc != Opcode) + return false; + + Inst.setOpcode(I->NewOpc); + // AVX variant of BLENDVPD/BLENDVPS/PBLENDVB instructions has more + // operand compare to SSE variant, which is added below + if (X86::isBLENDVPD(Opcode) || X86::isBLENDVPS(Opcode) || + X86::isPBLENDVB(Opcode)) + Inst.addOperand(Inst.getOperand(2)); + + return true; +} + bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) { + if (MCOptions.X86Sse2Avx && convertSSEToAVX(Inst)) + return true; + if (ForcedOpcodePrefix != OpcodePrefix_VEX3 && X86::optimizeInstFromVEX3ToVEX2(Inst, MII.get(Inst.getOpcode()))) return true; diff --git a/llvm/test/MC/AsmParser/sse2avx-att.s b/llvm/test/MC/AsmParser/sse2avx-att.s new file mode 100644 index 0000000000000..a452a5c611d3a --- /dev/null +++ b/llvm/test/MC/AsmParser/sse2avx-att.s @@ -0,0 +1,89 @@ +# RUN: llvm-mc -triple x86_64 -x86-sse2avx %s | FileCheck %s +# RUN: llvm-mc -triple=x86_64 -output-asm-variant=1 %s | llvm-mc -triple=x86_64 -x86-asm-syntax=intel -x86-sse2avx + .text +# CHECK: vmovsd -352(%rbp), %xmm0 + movsd -352(%rbp), %xmm0 # xmm0 = mem[0],zero +# CHECK-NEXT: vunpcklpd %xmm1, %xmm0, %xmm0 # xmm0 = xmm0[0],xmm1[0] + unpcklpd %xmm1, %xmm0 # xmm0 = xmm0[0],xmm1[0] +# CHECK-NEXT: vmovapd %xmm0, -368(%rbp) + movapd %xmm0, -368(%rbp) +# CHECK-NEXT: vmovapd -368(%rbp), %xmm0 + movapd -368(%rbp), %xmm0 +# CHECK-NEXT: vmovsd -376(%rbp), %xmm1 + movsd -376(%rbp), %xmm1 # xmm1 = mem[0],zero +# CHECK-NEXT: vmovsd -384(%rbp), %xmm0 + movsd -384(%rbp), %xmm0 # xmm0 = mem[0],zero +# CHECK-NEXT: vunpcklpd %xmm1, %xmm0, %xmm0 # xmm0 = xmm0[0],xmm1[0] + unpcklpd %xmm1, %xmm0 # xmm0 = xmm0[0],xmm1[0] +# CHECK-NEXT: vaddpd %xmm1, %xmm0, %xmm0 + addpd %xmm1, %xmm0 +# CHECK-NEXT: vmovapd %xmm0, -464(%rbp) + movapd %xmm0, -464(%rbp) +# CHECK-NEXT: vmovaps -304(%rbp), %xmm1 + movaps -304(%rbp), %xmm1 +# CHECK-NEXT: vpandn %xmm1, %xmm0, %xmm0 + pandn %xmm1, %xmm0 +# CHECK-NEXT: vmovaps %xmm0, -480(%rbp) + movaps %xmm0, -480(%rbp) +# CHECK-NEXT: vmovss -220(%rbp), %xmm1 + movss -220(%rbp), %xmm1 # xmm1 = mem[0],zero,zero,zero +# CHECK-NEXT: vinsertps $16, %xmm1, %xmm0, %xmm0 # xmm0 = xmm0[0],xmm1[0],xmm0[2,3] + insertps $16, %xmm1, %xmm0 # xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +# CHECK-NEXT: vmovaps %xmm0, -496(%rbp) + movaps %xmm0, -496(%rbp) +# CHECK-NEXT: vmovss -256(%rbp), %xmm0 + movss -256(%rbp), %xmm0 # xmm0 = mem[0],zero,zero,zero +# CHECK-NEXT: vmovaps -192(%rbp), %xmm0 + movaps -192(%rbp), %xmm0 +# CHECK-NEXT: vdivss %xmm1, %xmm0, %xmm0 + divss %xmm1, %xmm0 +# CHECK-NEXT: vmovaps %xmm0, -192(%rbp) + movaps %xmm0, -192(%rbp) +# CHECK-NEXT: vmovd -128(%rbp), %xmm0 + movd -128(%rbp), %xmm0 # xmm0 = mem[0],zero,zero,zero +# CHECK-NEXT: vpinsrd $1, %edx, %xmm0, %xmm0 + pinsrd $1, %edx, %xmm0 +# CHECK-NEXT: vmovaps %xmm0, -144(%rbp) + movaps %xmm0, -144(%rbp) +# CHECK-NEXT: vmovd -160(%rbp), %xmm0 + movd -160(%rbp), %xmm0 # xmm0 = mem[0],zero,zero,zero +# CHECK-NEXT: vpblendw $170, %xmm1, %xmm0, %xmm0 # xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3],xmm0[4],xmm1[5],xmm0[6],xmm1[7] + pblendw $170, %xmm1, %xmm0 # xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3],xmm0[4],xmm1[5],xmm0[6],xmm1[7] +# CHECK-NEXT: vmovdqa %xmm0, -576(%rbp) + movdqa %xmm0, -576(%rbp) +# CHECK-NEXT: vphsubw %xmm1, %xmm0, %xmm0 + phsubw %xmm1, %xmm0 +# CHECK-NEXT: vmovdqa %xmm0, -592(%rbp) + movdqa %xmm0, -592(%rbp) +# CHECK-NEXT: vmovaps -496(%rbp), %xmm0 + movaps -496(%rbp), %xmm0 +# CHECK-NEXT: vroundps $8, %xmm0, %xmm0 + roundps $8, %xmm0, %xmm0 +# CHECK-NEXT: vmovaps %xmm0, -608(%rbp) + movaps %xmm0, -608(%rbp) +# CHECK-NEXT: vmovapd -432(%rbp), %xmm0 + movapd -432(%rbp), %xmm0 +# CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0 + pxor %xmm1, %xmm0 +# CHECK-NEXT: vmovaps %xmm0, -640(%rbp) + movaps %xmm0, -640(%rbp) +# CHECK-NEXT: vmovapd -32(%rbp), %xmm0 + movapd -32(%rbp), %xmm0 +# CHECK-NEXT: vmovupd %xmm0, (%rax) + movupd %xmm0, (%rax) +# CHECK-NEXT: vmovsd -656(%rbp), %xmm0 + movsd -656(%rbp), %xmm0 # xmm0 = mem[0],zero +# CHECK-NEXT: extrq $16, $8, %xmm0 # xmm0 = xmm0[2],zero,zero,zero,zero,zero,zero,zero,xmm0[u,u,u,u,u,u,u,u] + extrq $16, $8, %xmm0 +# CHECK-NEXT: insertq $16, $8, %xmm1, %xmm0 # xmm0 = xmm0[0,1],xmm1[0],xmm0[3,4,5,6,7,u,u,u,u,u,u,u,u] + insertq $16, $8, %xmm1, %xmm0 +# CHECK-NEXT: pshufw $1, %mm0, %mm2 # mm2 = mm0[1,0,0,0] + pshufw $1, %mm0, %mm2 +# CHECK-NEXT: vpblendvb %xmm2, %xmm2, %xmm1, %xmm1 + pblendvb %xmm0, %xmm2, %xmm1 +# CHECK-NEXT: vblendvps %xmm0, %xmm0, %xmm2, %xmm2 + blendvps %xmm0, %xmm0, %xmm2 +# CHECK-NEXT: vblendvpd %xmm0, %xmm0, %xmm2, %xmm2 + blendvpd %xmm0, %xmm0, %xmm2 +# CHECK-NEXT: vblendvpd %xmm0, %xmm0, %xmm2, %xmm2 + blendvpd %xmm0, %xmm2 diff --git a/llvm/utils/TableGen/X86InstrMappingEmitter.cpp b/llvm/utils/TableGen/X86InstrMappingEmitter.cpp index 950ff1394b9fd..f967344135553 100644 --- a/llvm/utils/TableGen/X86InstrMappingEmitter.cpp +++ b/llvm/utils/TableGen/X86InstrMappingEmitter.cpp @@ -56,6 +56,8 @@ class X86InstrMappingEmitter { raw_ostream &OS); void emitND2NonNDTable(ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS); + void emitSSE2AVXTable(ArrayRef<const CodeGenInstruction *> Insts, + raw_ostream &OS); // Prints the definition of class X86TableEntry. void printClassDef(raw_ostream &OS); @@ -335,6 +337,38 @@ void X86InstrMappingEmitter::emitND2NonNDTable( printTable(Table, "X86ND2NonNDTable", "GET_X86_ND2NONND_TABLE", OS); } +void X86InstrMappingEmitter::emitSSE2AVXTable( + ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) { + + const std::map<StringRef, StringRef> ManualMap = { +#define ENTRY_SSE2AVX(OLD, NEW) {#OLD, #NEW}, +#include "X86ManualInstrMapping.def" + }; + + std::vector<Entry> Table; + for (const CodeGenInstruction *Inst : Insts) { + const Record *Rec = Inst->TheDef; + StringRef Name = Rec->getName(); + if (!isInteresting(Rec)) + continue; + if (ManualMap.find(Name) != ManualMap.end()) { + auto *NewRec = Records.getDef(ManualMap.at(Rec->getName())); + assert(NewRec && "Instruction not found!"); + auto &NewInst = Target.getInstruction(NewRec); + Table.push_back(std::pair(Inst, &NewInst)); + continue; + } + + std::string NewName = ("V" + Name).str(); + auto *AVXRec = Records.getDef(NewName); + if (!AVXRec) + continue; + auto &AVXInst = Target.getInstruction(AVXRec); + Table.push_back(std::pair(Inst, &AVXInst)); + } + printTable(Table, "X86SSE2AVXTable", "GET_X86_SSE2AVX_TABLE", OS); +} + void X86InstrMappingEmitter::run(raw_ostream &OS) { emitSourceFileHeader("X86 instruction mapping", OS); @@ -344,6 +378,7 @@ void X86InstrMappingEmitter::run(raw_ostream &OS) { emitCompressEVEXTable(Insts, OS); emitNFTransformTable(Insts, OS); emitND2NonNDTable(Insts, OS); + emitSSE2AVXTable(Insts, OS); } } // namespace diff --git a/llvm/utils/TableGen/X86ManualInstrMapping.def b/llvm/utils/TableGen/X86ManualInstrMapping.def index 364f15607f73d..58f5449f3b27b 100644 --- a/llvm/utils/TableGen/X86ManualInstrMapping.def +++ b/llvm/utils/TableGen/X86ManualInstrMapping.def @@ -349,3 +349,14 @@ NOCOMP_ND(CFCMOV64rr_ND) ENTRY_ND(MOVBE32rr, BSWAP32r) ENTRY_ND(MOVBE64rr, BSWAP64r) #undef ENTRY_ND + +#ifndef ENTRY_SSE2AVX +#define ENTRY_SSE2AVX(OLD, NEW) +#endif +ENTRY_SSE2AVX(BLENDVPDrm0, VBLENDVPDrmr) +ENTRY_SSE2AVX(BLENDVPDrr0, VBLENDVPDrrr) +ENTRY_SSE2AVX(BLENDVPSrm0, VBLENDVPSrmr) +ENTRY_SSE2AVX(BLENDVPSrr0, VBLENDVPSrrr) +ENTRY_SSE2AVX(PBLENDVBrm0, VPBLENDVBrmr) +ENTRY_SSE2AVX(PBLENDVBrr0, VPBLENDVBrrr) +#undef ENTRY_SSE2AVX _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits