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:
Elena Demikhovsky 2014-02-20 06:34:39 +00:00
parent 830f0c3899
commit c96570172a
3 changed files with 115 additions and 66 deletions

View File

@ -605,6 +605,13 @@ private:
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) {
Error(Loc, Msg);
return 0;
@ -652,6 +659,12 @@ private:
/// the parsing mode (Intel vs. AT&T).
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 {
// FIXME: Can tablegen auto-generate this?
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
/// has already been parsed if present.
X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
@ -2285,73 +2364,30 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
if (getLexer().is(AsmToken::Star))
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
// Read the first operand.
if (X86Operand *Op = ParseOperand())
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()) {
Operands.push_back(Op);
if (!getLexer().is(AsmToken::RCurly)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "Expected } at this point");
}
Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
} else {
Parser.eatToEndOfStatement();
// Read the operands.
while(1) {
if (X86Operand *Op = ParseOperand()) {
Operands.push_back(Op);
if (!HandleAVX512Operand(Operands, *Op))
return true;
}
} else {
Parser.eatToEndOfStatement();
return true;
}
// TODO: add parsing of broadcasts {1to8}, {1to16}
// 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") {
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 }
}
}
// check for comma and eat it
if (getLexer().is(AsmToken::Comma))
Parser.Lex();
else
break;
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
}
if (getLexer().isNot(AsmToken::EndOfStatement))
return ErrorAndEatStatement(getLexer().getLoc(), "unexpected token in argument list");
}
if (getLexer().is(AsmToken::EndOfStatement))
Parser.Lex(); // Consume the EndOfStatement
else if (isPrefix && getLexer().is(AsmToken::Slash))
Parser.Lex(); // Consume the prefix separator Slash
// Consume the EndOfStatement or the prefix separator Slash
if (getLexer().is(AsmToken::EndOfStatement) || isPrefix && getLexer().is(AsmToken::Slash))
Parser.Lex();
if (ExtraImmOp && isParsingIntelSyntax())
Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));

View File

@ -956,11 +956,16 @@ let Predicates = [HasAVX512] in {
(COPY_TO_REGCLASS (KMOVWkm addr:$src), VK8)>;
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))),
(COPY_TO_REGCLASS
(KMOVWkr (SUBREG_TO_REG (i32 0), GR8:$src, sub_8bit)), VK1)>;
(COPY_TO_REGCLASS
(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<(i8 (zext VK1:$src)),

View File

@ -51,3 +51,11 @@ vmovd %xmm22, -84(%rsp)
// CHECK: vextractps
// CHECK: encoding: [0x62,0xe3,0x7d,0x08,0x17,0x61,0x1f,0x02]
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