Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -749,6 +749,11 @@ bool HandleAVX512Operand(OperandVector &Operands, const MCParsedAsmOperand &Op); + bool ParseZ(std::unique_ptr &Z, bool IsExpected, + const SMLoc &StartLoc); + + bool ParseK(OperandVector &Operands, const SMLoc &StartLoc, bool *FoundK); + bool is64BitMode() const { // FIXME: Can tablegen auto-generate this? return getSTI().getFeatureBits()[X86::Mode64Bit]; @@ -1879,6 +1884,44 @@ } } +// False on failure, true otherwise +bool X86AsmParser::ParseZ(std::unique_ptr &Z, bool IsExpected, + const SMLoc &StartLoc) { + MCAsmParser &Parser = getParser(); + // Assuming we are just pass the '{' mark, quering the next token + bool FoundZ = getLexer().is(AsmToken::Identifier) && + (getLexer().getTok().getIdentifier() == "z"); + // Expected {z}, but none was found + if (IsExpected && !FoundZ) + return !Error(getLexer().getLoc(), "Expected z at this point"); + else if (!FoundZ) + return true; + Parser.Lex(); // Eat z + // Query and eat the '}' mark + if (!getLexer().is(AsmToken::RCurly)) + return !Error(getLexer().getLoc(), "Expected } at this point"); + Parser.Lex(); + Z.reset(X86Operand::CreateToken("{z}", StartLoc).release()); + return true; +} + +// False on failure, true otherwise +bool X86AsmParser::ParseK(OperandVector &Operands, const SMLoc &StartLoc, + bool *FoundK) { + assert(FoundK); + *FoundK = false; + // Assuming we are just pass the '{' mark, quering the next token + if (std::unique_ptr Op = ParseOperand()) { + if (!getLexer().is(AsmToken::RCurly)) + return !Error(getLexer().getLoc(), "Expected } at this point"); + Operands.push_back(X86Operand::CreateToken("{", StartLoc)); + Operands.push_back(std::move(Op)); + Operands.push_back(X86Operand::CreateToken("}", consumeToken())); + *FoundK = true; + } + return true; +} + bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands, const MCParsedAsmOperand &Op) { MCAsmParser &Parser = getParser(); @@ -1915,26 +1958,24 @@ // after memory broadcasting, so return. return true; } else { - // Parse mask register {%k1} - Operands.push_back(X86Operand::CreateToken("{", consumedToken)); - if (std::unique_ptr Op = ParseOperand()) { - Operands.push_back(std::move(Op)); - if (!getLexer().is(AsmToken::RCurly)) - return !TokError("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 !TokError("Expected z at this point"); - Parser.Lex(); // Eat the z - if (!getLexer().is(AsmToken::RCurly)) - return !TokError("Expected } at this point"); - Parser.Lex(); // Eat the } - } + // Parse either {k}{z}, {z}{k}, {k} or {z} + // last one have no meaning, but GCC accepts it + std::unique_ptr Z; + bool FoundK = false; + if (!ParseZ(Z, false, consumedToken)) + return false; + if (Z ? getLexer().is(AsmToken::LCurly) : true) { + if (!ParseK(Operands, Z ? consumeToken() : consumedToken, &FoundK)) + return false; + if (FoundK && getLexer().is(AsmToken::LCurly) && !Z) + if (!ParseZ(Z, true, consumeToken())) + return false; } + // '{z}' on its own is meaningless, hence should be ignored. + // on the contrary - have it been accompanied by a K register, + // allow it. + if (FoundK && Z) + Operands.push_back(std::move(Z)); } } } Index: test/MC/X86/avx512bw-encoding.s =================================================================== --- test/MC/X86/avx512bw-encoding.s +++ test/MC/X86/avx512bw-encoding.s @@ -12,6 +12,10 @@ // CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9] vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z} +// CHECK: vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z} +// CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9] + vpblendmb %zmm25, %zmm18, %zmm17 {z} {%k5} + // CHECK: vpblendmb (%rcx), %zmm18, %zmm17 // CHECK: encoding: [0x62,0xe2,0x6d,0x40,0x66,0x09] vpblendmb (%rcx), %zmm18, %zmm17 Index: test/MC/X86/intel-syntax-avx512.s =================================================================== --- test/MC/X86/intel-syntax-avx512.s +++ test/MC/X86/intel-syntax-avx512.s @@ -16,6 +16,10 @@ // CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] vaddpd zmm1 {k5} {z}, zmm1, zmm2 +// CHECK: vaddpd zmm1 {k5} {z}, zmm1, zmm2 +// CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] +vaddpd zmm1 {z} {k5}, zmm1, zmm2 + // CHECK: vaddpd zmm1, zmm1, zmm2, {rn-sae} // CHECK: encoding: [0x62,0xf1,0xf5,0x18,0x58,0xca] vaddpd zmm1, zmm1, zmm2, {rn-sae}