[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