[llvm] [X86][MC] Added support for -msse2avx option in llvm-mc (PR #96860)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 00:19:51 PDT 2024


https://github.com/JaydeepChauhan14 created https://github.com/llvm/llvm-project/pull/96860

- Implemented "-msse2avx" option, which is converts SSE instructions to AVX instructions.
- GCC already have this option https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/x86-Options.html.

>From b4a534ad6f811cf0868b7fd1ee641fae8502e171 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Thu, 27 Jun 2024 15:17:50 +0800
Subject: [PATCH] [X86][MC] Added support for -msse2avx option in llvm-mc

---
 llvm/include/llvm/MC/MCTargetOptions.h        |  1 +
 .../llvm/MC/MCTargetOptionsCommandFlags.h     |  2 +
 llvm/lib/MC/MCTargetOptions.cpp               |  2 +-
 llvm/lib/MC/MCTargetOptionsCommandFlags.cpp   |  6 ++
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 20 +++++
 llvm/test/MC/AsmParser/sse2avx.s              | 74 +++++++++++++++++++
 .../utils/TableGen/X86InstrMappingEmitter.cpp | 28 +++++++
 7 files changed, 132 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/MC/AsmParser/sse2avx.s

diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index 0cf2806bd4804..90fe356d47077 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -55,6 +55,7 @@ class MCTargetOptions {
   bool ShowMCEncoding : 1;
   bool ShowMCInst : 1;
   bool AsmVerbose : 1;
+  bool SSE2AVX : 1;
 
   /// Preserve Comments in Assembly.
   bool PreserveAsmComments : 1;
diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index dc33f7461ab28..2b5f74fc6c1d8 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -41,6 +41,8 @@ bool getEmitCompactUnwindNonCanonical();
 
 bool getShowMCInst();
 
+bool getSSE2AVX();
+
 bool getFatalWarnings();
 
 bool getNoWarn();
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index bff4b8da2fb1b..227d9fc347e71 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -16,7 +16,7 @@ MCTargetOptions::MCTargetOptions()
       MCNoWarn(false), MCNoDeprecatedWarn(false), MCNoTypeCheck(false),
       MCSaveTempLabels(false), MCIncrementalLinkerCompatible(false),
       FDPIC(false), ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
-      PreserveAsmComments(true), Dwarf64(false),
+      SSE2AVX(false), PreserveAsmComments(true), Dwarf64(false),
       EmitDwarfUnwind(EmitDwarfUnwindType::Default),
       MCUseDwarfDirectory(DefaultDwarfDirectory),
       EmitCompactUnwindNonCanonical(false), PPCUseFullRegisterNames(false) {}
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 2c378643797da..6de42fa981e6d 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -42,6 +42,7 @@ MCOPT(bool, Dwarf64)
 MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
 MCOPT(bool, EmitCompactUnwindNonCanonical)
 MCOPT(bool, ShowMCInst)
+MCOPT(bool, SSE2AVX)
 MCOPT(bool, FatalWarnings)
 MCOPT(bool, NoWarn)
 MCOPT(bool, NoDeprecatedWarn)
@@ -107,6 +108,10 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
       cl::desc("Emit internal instruction representation to assembly file"));
   MCBINDOPT(ShowMCInst);
 
+  static cl::opt<bool> SSE2AVX(
+      "msse2avx", cl::desc("Convert SSE Instructions to AVX Instructions"));
+  MCBINDOPT(SSE2AVX);
+
   static cl::opt<bool> FatalWarnings("fatal-warnings",
                                      cl::desc("Treat warnings as errors"));
   MCBINDOPT(FatalWarnings);
@@ -156,6 +161,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
   Options.Dwarf64 = getDwarf64();
   Options.DwarfVersion = getDwarfVersion();
   Options.ShowMCInst = getShowMCInst();
+  Options.SSE2AVX = getSSE2AVX();
   Options.ABIName = getABIName();
   Options.MCFatalWarnings = getFatalWarnings();
   Options.MCNoWarn = getNoWarn();
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index dbea42d55b5fc..ab70fdbc70caa 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
@@ -4141,6 +4145,15 @@ unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
   return Match_Success;
 }
 
+void ReplaceSSE2AVXOpcode(llvm::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) {
+    Inst.setOpcode(I->NewOpc);
+  }
+}
+
 bool X86AsmParser::matchAndEmitATTInstruction(
     SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,
     MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {
@@ -4159,6 +4172,13 @@ bool X86AsmParser::matchAndEmitATTInstruction(
     SwitchMode(X86::Is16Bit);
     ForcedDataPrefix = 0;
   }
+
+  // When "-msse2avx" option is enabled ReplaceSSE2AVXOpcode method will
+  // replace SSE instruction with equivalent AVX instruction using mapping given
+  // in table GET_X86_SSE2AVX_TABLE
+  if (MCOptions.SSE2AVX)
+    ReplaceSSE2AVXOpcode(Inst);
+
   switch (OriginalError) {
   default: llvm_unreachable("Unexpected match result!");
   case Match_Success:
diff --git a/llvm/test/MC/AsmParser/sse2avx.s b/llvm/test/MC/AsmParser/sse2avx.s
new file mode 100644
index 0000000000000..ee0c1251478b3
--- /dev/null
+++ b/llvm/test/MC/AsmParser/sse2avx.s
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -triple x86_64-unknown-unknown -msse2avx %s | FileCheck %s
+	.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
diff --git a/llvm/utils/TableGen/X86InstrMappingEmitter.cpp b/llvm/utils/TableGen/X86InstrMappingEmitter.cpp
index 950ff1394b9fd..770943177551f 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,31 @@ void X86InstrMappingEmitter::emitND2NonNDTable(
   printTable(Table, "X86ND2NonNDTable", "GET_X86_ND2NONND_TABLE", OS);
 }
 
+// Method emitSSE2AVXTable will create table GET_X86_SSE2AVX_TABLE for SSE to
+// AVX instruction mapping in X86GenInstrMapping.inc file, In table first entry
+// will be SSE instruction and second entry will be equivalent AVX instruction
+// Example:-  "{ X86::ADDPDrm, X86::VADDPDrm },"
+void X86InstrMappingEmitter::emitSSE2AVXTable(
+    ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
+  std::vector<Entry> Table;
+  for (const CodeGenInstruction *Inst : Insts) {
+    const Record *Rec = Inst->TheDef;
+    StringRef Name = Rec->getName();
+
+    auto *NewRec = Records.getDef(Name);
+    if (!NewRec)
+      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 +371,7 @@ void X86InstrMappingEmitter::run(raw_ostream &OS) {
   emitCompressEVEXTable(Insts, OS);
   emitNFTransformTable(Insts, OS);
   emitND2NonNDTable(Insts, OS);
+  emitSSE2AVXTable(Insts, OS);
 }
 } // namespace
 



More information about the llvm-commits mailing list