From 18fd49602b4e5c1c141a19f031b9f6d5caa7a423 Mon Sep 17 00:00:00 2001 From: Elena Demikhovsky Date: Mon, 2 Mar 2015 15:00:34 +0000 Subject: [PATCH] AVX-512: Add assembly parser support for Rounding mode By Asaf Badouh llvm-svn: 230962 --- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 42 ++++++++++++++++++++++++++ llvm/lib/Target/X86/AsmParser/X86Operand.h | 8 ++++- llvm/lib/Target/X86/X86InstrInfo.td | 5 ++- llvm/test/MC/X86/intel-syntax-avx512.s | 29 ++++++++++++++++++ llvm/test/MC/X86/x86-64-avx512f_vl.s | 33 ++++++++++++++++++++ 5 files changed, 115 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 0b6fb52..c24805a6 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -11,6 +11,7 @@ #include "X86AsmInstrumentation.h" #include "X86AsmParserCommon.h" #include "X86Operand.h" +#include "X86ISelLowering.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" @@ -664,6 +665,7 @@ private: ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size); std::unique_ptr ParseIntelMemOperand(int64_t ImmDisp, SMLoc StartLoc, unsigned Size); + std::unique_ptr ParseRoundingModeOp(SMLoc Start, SMLoc End); bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); std::unique_ptr ParseIntelBracExpression(unsigned SegReg, SMLoc Start, @@ -1407,6 +1409,35 @@ X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, /*Scale=*/1, Start, End, Size, Identifier, Info); } +//ParseRoundingModeOp - Parse AVX-512 rounding mode operand +std::unique_ptr +X86AsmParser::ParseRoundingModeOp(SMLoc Start, SMLoc End) { + MCAsmParser &Parser = getParser(); + const AsmToken &Tok = Parser.getTok(); + consumeToken(); // Eat "{" + if (Tok.getIdentifier().startswith("r")){ + int rndMode = StringSwitch(Tok.getIdentifier()) + .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT) + .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF) + .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF) + .Case("rz", X86::STATIC_ROUNDING::TO_ZERO) + .Default(-1); + if (-1 == rndMode) + return ErrorOperand(Tok.getLoc(), "Invalid rounding mode."); + Parser.Lex(); // Eat "r*" of r*-sae + if (!getLexer().is(AsmToken::Minus)) + return ErrorOperand(Tok.getLoc(), "Expected - at this point"); + Parser.Lex(); // Eat "-" + Parser.Lex(); // Eat the sae + if (!getLexer().is(AsmToken::RCurly)) + return ErrorOperand(Tok.getLoc(), "Expected } at this point"); + Parser.Lex(); // Eat "}" + const MCExpr *RndModeOp = + MCConstantExpr::Create(rndMode, Parser.getContext()); + return X86Operand::CreateImm(RndModeOp, Start, End); + } + return ErrorOperand(Tok.getLoc(), "unknown token in expression"); +} /// ParseIntelMemOperand - Parse intel style memory operand. std::unique_ptr X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, SMLoc Start, @@ -1656,6 +1687,11 @@ std::unique_ptr X86AsmParser::ParseIntelOperand() { return ParseIntelMemOperand(Imm, Start, Size); } + // rounding mode token + if (STI.getFeatureBits() & X86::FeatureAVX512 && + getLexer().is(AsmToken::LCurly)) + return ParseRoundingModeOp(Start, End); + // Register. unsigned RegNo = 0; if (!ParseRegister(RegNo, Start, End)) { @@ -1708,6 +1744,12 @@ std::unique_ptr X86AsmParser::ParseATTOperand() { return nullptr; return X86Operand::CreateImm(Val, Start, End); } + case AsmToken::LCurly:{ + SMLoc Start = Parser.getTok().getLoc(), End; + if (STI.getFeatureBits() & X86::FeatureAVX512) + return ParseRoundingModeOp(Start, End); + return ErrorOperand(Start, "unknown token in expression"); + } } } diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h index d67e119..94dbedb 100644 --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -260,6 +260,9 @@ struct X86Operand : public MCParsedAsmOperand { return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && !getMemIndexReg() && getMemScale() == 1; } + bool isAVX512RC() const{ + return isImm(); + } bool isAbsMem16() const { return isAbsMem() && Mem.ModeSize == 16; @@ -394,7 +397,10 @@ struct X86Operand : public MCParsedAsmOperand { RegNo = getGR32FromGR64(RegNo); Inst.addOperand(MCOperand::CreateReg(RegNo)); } - + void addAVX512RCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); addExpr(Inst, getImm()); diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 7ab8822..13bfe2d 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -572,10 +572,13 @@ def X86GR32orGR64AsmOperand : AsmOperandClass { def GR32orGR64 : RegisterOperand { let ParserMatchClass = X86GR32orGR64AsmOperand; } - +def AVX512RCOperand : AsmOperandClass { + let Name = "AVX512RC"; +} def AVX512RC : Operand { let PrintMethod = "printRoundingControl"; let OperandType = "OPERAND_IMMEDIATE"; + let ParserMatchClass = AVX512RCOperand; } // Sign-extended immediate classes. We don't need to define the full lattice diff --git a/llvm/test/MC/X86/intel-syntax-avx512.s b/llvm/test/MC/X86/intel-syntax-avx512.s index b382994..af4e98c 100644 --- a/llvm/test/MC/X86/intel-syntax-avx512.s +++ b/llvm/test/MC/X86/intel-syntax-avx512.s @@ -3,3 +3,32 @@ // CHECK: vaddps (%rax), %zmm1, %zmm1 // CHECK: encoding: [0x62,0xf1,0x74,0x48,0x58,0x08] vaddps zmm1, zmm1, zmmword ptr [rax] + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x48,0x58,0xca] +vaddpd zmm1,zmm1,zmm2 + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 {%k5} +// CHECK: encoding: [0x62,0xf1,0xf5,0x4d,0x58,0xca] +vaddpd zmm1{k5},zmm1,zmm2 + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 {%k5} {z} +// CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] +vaddpd zmm1{k5} {z},zmm1,zmm2 + +// CHECK: vaddpd {rn-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x18,0x58,0xca] +vaddpd zmm1,zmm1,zmm2,{rn-sae} + +// CHECK: vaddpd {ru-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x58,0x58,0xca] +vaddpd zmm1,zmm1,zmm2,{ru-sae} + +// CHECK: vaddpd {rd-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x38,0x58,0xca] +vaddpd zmm1,zmm1,zmm2,{rd-sae} + +// CHECK: vaddpd {rz-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x78,0x58,0xca] +vaddpd zmm1,zmm1,zmm2,{rz-sae} + diff --git a/llvm/test/MC/X86/x86-64-avx512f_vl.s b/llvm/test/MC/X86/x86-64-avx512f_vl.s index ad121dc..fd6df72 100644 --- a/llvm/test/MC/X86/x86-64-avx512f_vl.s +++ b/llvm/test/MC/X86/x86-64-avx512f_vl.s @@ -6651,3 +6651,36 @@ // CHECK: vmovups %ymm23, -4128(%rdx) // CHECK: encoding: [0x62,0xe1,0x7c,0x28,0x11,0xba,0xe0,0xef,0xff,0xff] vmovups %ymm23, -4128(%rdx) + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x48,0x58,0xca] +vaddpd %zmm2, %zmm1, %zmm1 + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 {%k5} +// CHECK: encoding: [0x62,0xf1,0xf5,0x4d,0x58,0xca] +vaddpd %zmm2, %zmm1, %zmm1 {%k5} + +// CHECK: vaddpd %zmm2, %zmm1, %zmm1 {%k5} {z} +// CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] +vaddpd %zmm2, %zmm1, %zmm1 {%k5} {z} + +// CHECK: vaddpd {rn-sae}, %zmm2, %zmm1, %zmm1 {%k5} {z} +// CHECK: encoding: [0x62,0xf1,0xf5,0x9d,0x58,0xca] +vaddpd {rn-sae}, %zmm2, %zmm1, %zmm1 {%k5} {z} + +// CHECK: vaddpd {rn-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x18,0x58,0xca] +vaddpd {rn-sae}, %zmm2, %zmm1, %zmm1 + +// CHECK: vaddpd {ru-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x58,0x58,0xca] +vaddpd {ru-sae}, %zmm2, %zmm1, %zmm1 + +// CHECK: vaddpd {rd-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x38,0x58,0xca] +vaddpd {rd-sae}, %zmm2, %zmm1, %zmm1 + +// CHECK: vaddpd {rz-sae}, %zmm2, %zmm1, %zmm1 +// CHECK: encoding: [0x62,0xf1,0xf5,0x78,0x58,0xca] +vaddpd {rz-sae}, %zmm2, %zmm1, %zmm1 + -- 2.7.4