-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[X86][MC,Driver] Support -msse2avx to encode SSE instruction with VEX prefix #96860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-backend-x86 @llvm/pr-subscribers-mc Author: None (JaydeepChauhan14) Changes
Full diff: https://github.com/llvm/llvm-project/pull/96860.diff 7 Files Affected:
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
|
@KanRobert , @phoebewang please review |
The document says it's GCC option and turn on with |
It's binutils flag https://godbolt.org/z/o9MM9br95. GCC only forwards it to AS. |
If it's simply forward, why inline asm is not affected? |
It only works when input file is .s, e.g gcc -c -msse2avx 1.s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - cheers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This driver option needs a TargetSpecific
flag, otherwise this LGTM.
@JaydeepChauhan14 Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested Please check whether problems have been caused by your change specifically, as How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/154/builds/1430 Here is the relevant piece of the build log for the reference:
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/1438 Here is the relevant piece of the build log for the reference:
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/17/builds/869 Here is the relevant piece of the build log for the reference:
|
The test was added in #96860
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/176/builds/1120 Here is the relevant piece of the build log for the reference:
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/13/builds/785 Here is the relevant piece of the build log for the reference:
|
… prefix (#96860) Summary: For GCC compatibility https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/x86-Options.html. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251694
Summary: The test was added in #96860 Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251552
* Initialize `X86RelaxRelocations`. * Fix #96860 test to actually test -Wa,-msse2avx for non-x86.
For GCC compatibility https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/x86-Options.html.