mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
AVX-512: Assembly parsing of broadcast semantic in AVX-512; imlemented by Nis Zinovy (zinovy.y.nis@intel.com)
Fixed truncate i32 to i1; a test will be provided in the next commit. llvm-svn: 201757
This commit is contained in:
parent
e9728e0d5b
commit
af8e1ef280
@ -605,6 +605,13 @@ private:
|
|||||||
return Parser.Error(L, Msg, Ranges);
|
return Parser.Error(L, Msg, Ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ErrorAndEatStatement(SMLoc L, const Twine &Msg,
|
||||||
|
ArrayRef<SMRange> Ranges = None,
|
||||||
|
bool MatchingInlineAsm = false) {
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
return Error(L, Msg, Ranges, MatchingInlineAsm);
|
||||||
|
}
|
||||||
|
|
||||||
X86Operand *ErrorOperand(SMLoc Loc, StringRef Msg) {
|
X86Operand *ErrorOperand(SMLoc Loc, StringRef Msg) {
|
||||||
Error(Loc, Msg);
|
Error(Loc, Msg);
|
||||||
return 0;
|
return 0;
|
||||||
@ -652,6 +659,12 @@ private:
|
|||||||
/// the parsing mode (Intel vs. AT&T).
|
/// the parsing mode (Intel vs. AT&T).
|
||||||
bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2);
|
bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2);
|
||||||
|
|
||||||
|
/// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
|
||||||
|
/// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
|
||||||
|
/// \return \c true if no parsing errors occurred, \c false otherwise.
|
||||||
|
bool HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
|
const MCParsedAsmOperand &Op);
|
||||||
|
|
||||||
bool is64BitMode() const {
|
bool is64BitMode() const {
|
||||||
// FIXME: Can tablegen auto-generate this?
|
// FIXME: Can tablegen auto-generate this?
|
||||||
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
|
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
|
||||||
@ -2027,6 +2040,72 @@ X86Operand *X86AsmParser::ParseATTOperand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86AsmParser::HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
|
const MCParsedAsmOperand &Op) {
|
||||||
|
if(STI.getFeatureBits() & X86::FeatureAVX512) {
|
||||||
|
if (getLexer().is(AsmToken::LCurly)) {
|
||||||
|
// Eat "{" and mark the current place.
|
||||||
|
const SMLoc consumedToken = consumeToken();
|
||||||
|
// Distinguish {1to<NUM>} from {%k<NUM>}.
|
||||||
|
if(getLexer().is(AsmToken::Integer)) {
|
||||||
|
// Parse memory broadcasting ({1to<NUM>}).
|
||||||
|
if (getLexer().getTok().getIntVal() != 1)
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected 1to<NUM> at this point");
|
||||||
|
Parser.Lex(); // Eat "1" of 1to8
|
||||||
|
if (!getLexer().is(AsmToken::Identifier) ||
|
||||||
|
!getLexer().getTok().getIdentifier().startswith("to"))
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected 1to<NUM> at this point");
|
||||||
|
// Recognize only reasonable suffixes.
|
||||||
|
const char *BroadcastPrimitive =
|
||||||
|
StringSwitch<const char*>(getLexer().getTok().getIdentifier())
|
||||||
|
.Case("to8", "{1to8}")
|
||||||
|
.Case("to16", "{1to16}")
|
||||||
|
.Default(0);
|
||||||
|
if (!BroadcastPrimitive)
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Invalid memory broadcast primitive.");
|
||||||
|
Parser.Lex(); // Eat "toN" of 1toN
|
||||||
|
if (!getLexer().is(AsmToken::RCurly))
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected } at this point");
|
||||||
|
Parser.Lex(); // Eat "}"
|
||||||
|
Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
|
||||||
|
consumedToken));
|
||||||
|
// No AVX512 specific primitives can pass
|
||||||
|
// after memory broadcasting, so return.
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Parse mask register {%k1}
|
||||||
|
Operands.push_back(X86Operand::CreateToken("{", consumedToken));
|
||||||
|
if (X86Operand *Op = ParseOperand()) {
|
||||||
|
Operands.push_back(Op);
|
||||||
|
if (!getLexer().is(AsmToken::RCurly))
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected } at this point");
|
||||||
|
Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
|
||||||
|
|
||||||
|
// Parse "zeroing non-masked" semantic {z}
|
||||||
|
if (getLexer().is(AsmToken::LCurly)) {
|
||||||
|
Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
|
||||||
|
if (!getLexer().is(AsmToken::Identifier) ||
|
||||||
|
getLexer().getTok().getIdentifier() != "z")
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected z at this point");
|
||||||
|
Parser.Lex(); // Eat the z
|
||||||
|
if (!getLexer().is(AsmToken::RCurly))
|
||||||
|
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||||
|
"Expected } at this point");
|
||||||
|
Parser.Lex(); // Eat the }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
|
/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
|
||||||
/// has already been parsed if present.
|
/// has already been parsed if present.
|
||||||
X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
|
X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
|
||||||
@ -2285,73 +2364,30 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
|||||||
if (getLexer().is(AsmToken::Star))
|
if (getLexer().is(AsmToken::Star))
|
||||||
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
|
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
|
||||||
|
|
||||||
// Read the first operand.
|
// Read the operands.
|
||||||
if (X86Operand *Op = ParseOperand())
|
while(1) {
|
||||||
Operands.push_back(Op);
|
|
||||||
else {
|
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (getLexer().is(AsmToken::Comma)) {
|
|
||||||
Parser.Lex(); // Eat the comma.
|
|
||||||
|
|
||||||
// Parse and remember the operand.
|
|
||||||
if (X86Operand *Op = ParseOperand())
|
|
||||||
Operands.push_back(Op);
|
|
||||||
else {
|
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (STI.getFeatureBits() & X86::FeatureAVX512) {
|
|
||||||
// Parse mask register {%k1}
|
|
||||||
if (getLexer().is(AsmToken::LCurly)) {
|
|
||||||
Operands.push_back(X86Operand::CreateToken("{", consumeToken()));
|
|
||||||
if (X86Operand *Op = ParseOperand()) {
|
if (X86Operand *Op = ParseOperand()) {
|
||||||
Operands.push_back(Op);
|
Operands.push_back(Op);
|
||||||
if (!getLexer().is(AsmToken::RCurly)) {
|
if (!HandleAVX512Operand(Operands, *Op))
|
||||||
SMLoc Loc = getLexer().getLoc();
|
return true;
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return Error(Loc, "Expected } at this point");
|
|
||||||
}
|
|
||||||
Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
|
|
||||||
} else {
|
} else {
|
||||||
Parser.eatToEndOfStatement();
|
Parser.eatToEndOfStatement();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
// check for comma and eat it
|
||||||
// TODO: add parsing of broadcasts {1to8}, {1to16}
|
if (getLexer().is(AsmToken::Comma))
|
||||||
// Parse "zeroing non-masked" semantic {z}
|
Parser.Lex();
|
||||||
if (getLexer().is(AsmToken::LCurly)) {
|
else
|
||||||
Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
|
break;
|
||||||
if (!getLexer().is(AsmToken::Identifier) || getLexer().getTok().getIdentifier() != "z") {
|
|
||||||
SMLoc Loc = getLexer().getLoc();
|
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return Error(Loc, "Expected z at this point");
|
|
||||||
}
|
|
||||||
Parser.Lex(); // Eat the z
|
|
||||||
if (!getLexer().is(AsmToken::RCurly)) {
|
|
||||||
SMLoc Loc = getLexer().getLoc();
|
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return Error(Loc, "Expected } at this point");
|
|
||||||
}
|
|
||||||
Parser.Lex(); // Eat the }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||||
SMLoc Loc = getLexer().getLoc();
|
return ErrorAndEatStatement(getLexer().getLoc(), "unexpected token in argument list");
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return Error(Loc, "unexpected token in argument list");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getLexer().is(AsmToken::EndOfStatement))
|
// Consume the EndOfStatement or the prefix separator Slash
|
||||||
Parser.Lex(); // Consume the EndOfStatement
|
if (getLexer().is(AsmToken::EndOfStatement) || isPrefix && getLexer().is(AsmToken::Slash))
|
||||||
else if (isPrefix && getLexer().is(AsmToken::Slash))
|
Parser.Lex();
|
||||||
Parser.Lex(); // Consume the prefix separator Slash
|
|
||||||
|
|
||||||
if (ExtraImmOp && isParsingIntelSyntax())
|
if (ExtraImmOp && isParsingIntelSyntax())
|
||||||
Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
|
Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
|
||||||
|
@ -956,11 +956,16 @@ let Predicates = [HasAVX512] in {
|
|||||||
(COPY_TO_REGCLASS (KMOVWkm addr:$src), VK8)>;
|
(COPY_TO_REGCLASS (KMOVWkm addr:$src), VK8)>;
|
||||||
|
|
||||||
def : Pat<(i1 (trunc (i32 GR32:$src))),
|
def : Pat<(i1 (trunc (i32 GR32:$src))),
|
||||||
(COPY_TO_REGCLASS (KMOVWkr $src), VK1)>;
|
(COPY_TO_REGCLASS (KMOVWkr (AND32ri $src, (i32 1))), VK1)>;
|
||||||
|
|
||||||
def : Pat<(i1 (trunc (i8 GR8:$src))),
|
def : Pat<(i1 (trunc (i8 GR8:$src))),
|
||||||
(COPY_TO_REGCLASS
|
(COPY_TO_REGCLASS
|
||||||
(KMOVWkr (SUBREG_TO_REG (i32 0), GR8:$src, sub_8bit)), VK1)>;
|
(KMOVWkr (AND32ri (SUBREG_TO_REG (i32 0), GR8:$src, sub_8bit), (i32 1))),
|
||||||
|
VK1)>;
|
||||||
|
def : Pat<(i1 (trunc (i16 GR16:$src))),
|
||||||
|
(COPY_TO_REGCLASS
|
||||||
|
(KMOVWkr (AND32ri (SUBREG_TO_REG (i32 0), $src, sub_16bit), (i32 1))),
|
||||||
|
VK1)>;
|
||||||
|
|
||||||
def : Pat<(i32 (zext VK1:$src)), (KMOVWrk (COPY_TO_REGCLASS VK1:$src, VK16))>;
|
def : Pat<(i32 (zext VK1:$src)), (KMOVWrk (COPY_TO_REGCLASS VK1:$src, VK16))>;
|
||||||
def : Pat<(i8 (zext VK1:$src)),
|
def : Pat<(i8 (zext VK1:$src)),
|
||||||
|
@ -51,3 +51,11 @@ vmovd %xmm22, -84(%rsp)
|
|||||||
// CHECK: vextractps
|
// CHECK: vextractps
|
||||||
// CHECK: encoding: [0x62,0xe3,0x7d,0x08,0x17,0x61,0x1f,0x02]
|
// CHECK: encoding: [0x62,0xe3,0x7d,0x08,0x17,0x61,0x1f,0x02]
|
||||||
vextractps $2, %xmm20, 124(%rcx)
|
vextractps $2, %xmm20, 124(%rcx)
|
||||||
|
|
||||||
|
// CHECK: vaddpd {{.*}}{1to8}
|
||||||
|
// CHECK: encoding: [0x62,0x61,0xdd,0x50,0x58,0x74,0xf7,0x40]
|
||||||
|
vaddpd 512(%rdi, %rsi, 8) {1to8}, %zmm20, %zmm30
|
||||||
|
|
||||||
|
// CHECK: vaddps {{.*}}{1to16}
|
||||||
|
// CHECK: encoding: [0x62,0x61,0x5c,0x50,0x58,0xb4,0xf7,0x00,0x02,0x00,0x00]
|
||||||
|
vaddps 512(%rdi, %rsi, 8) {1to16}, %zmm20, %zmm30
|
||||||
|
Loading…
Reference in New Issue
Block a user