diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index d4a185041f3..5a8707b5d12 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -221,6 +221,11 @@ class Instruction { bit mayHaveSideEffects = 0; bit neverHasSideEffects = 0; + // Is this instruction a "real" instruction (with a distinct machine + // encoding), or is it a pseudo instruction used for codegen modeling + // purposes. + bit isCodeGenOnly = 0; + InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. string Constraints = ""; // OperandConstraint, e.g. $src = $dst. @@ -386,7 +391,8 @@ class InstrInfo { bit isLittleEndianEncoding = 0; } -// Standard Instructions. +// Standard Pseudo Instructions. +let isCodeGenOnly = 1 in { def PHI : Instruction { let OutOperandList = (ops); let InOperandList = (ops variable_ops); @@ -466,6 +472,7 @@ def COPY_TO_REGCLASS : Instruction { let neverHasSideEffects = 1; let isAsCheapAsAMove = 1; } +} //===----------------------------------------------------------------------===// // AsmParser - This class can be implemented by targets that wish to implement diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index fbfde7d6d2e..8c808118358 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -3166,7 +3166,8 @@ let neverHasSideEffects = 1 in { // Alias instructions that map movr0 to xor. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. -let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1 in { +let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, + isCodeGenOnly = 1 in { def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "xor{b}\t$dst, $dst", [(set GR8:$dst, 0)]>; diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index dfdf700e466..ce76b4e8b11 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -516,7 +516,7 @@ def MMX_MASKMOVQ64: MMXI64<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), //===----------------------------------------------------------------------===// // Alias instructions that map zero vector to pxor. -let isReMaterializable = 1 in { +let isReMaterializable = 1, isCodeGenOnly = 1 in { def MMX_V_SET0 : MMXI<0xEF, MRMInitReg, (outs VR64:$dst), (ins), "pxor\t$dst, $dst", [(set VR64:$dst, (v2i32 immAllZerosV))]>; diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 4547ad2c482..f5965271ae2 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -472,7 +472,7 @@ def Int_COMISSrm: PSI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), // that start with 'Fs'. // Alias instructions that map fld0 to pxor for sse. -let isReMaterializable = 1, isAsCheapAsAMove = 1 in +let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1 in def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "pxor\t$dst, $dst", [(set FR32:$dst, fp32imm0)]>, Requires<[HasSSE1]>, TB, OpSize; @@ -992,7 +992,8 @@ def STMXCSR : PSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), // Alias instructions that map zero vector to pxor / xorp* for sse. // We set canFoldAsLoad because this can be converted to a constant-pool // load of an all-zeros value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1 in +let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, + isCodeGenOnly = 1 in def V_SET0 : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "xorps\t$dst, $dst", [(set VR128:$dst, (v4i32 immAllZerosV))]>; @@ -1208,7 +1209,7 @@ def Int_COMISDrm: PDI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), // that start with 'Fs'. // Alias instructions that map fld0 to pxor for sse. -let isReMaterializable = 1, isAsCheapAsAMove = 1 in +let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1 in def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "pxor\t$dst, $dst", [(set FR64:$dst, fpimm0)]>, Requires<[HasSSE2]>, TB, OpSize; @@ -2245,7 +2246,8 @@ def : Pat<(membarrier (i8 imm:$ll), (i8 imm:$ls), (i8 imm:$sl), (i8 imm:$ss), // Alias instructions that map zero vector to pxor / xorp* for sse. // We set canFoldAsLoad because this can be converted to a constant-pool // load of an all-ones value if folding it would be beneficial. -let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1 in +let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, + isCodeGenOnly = 1 in def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "pcmpeqd\t$dst, $dst", [(set VR128:$dst, (v4i32 immAllOnesV))]>; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 4dbd24c70db..122f12476b7 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -210,18 +210,17 @@ static void TokenizeAsmString(const StringRef &AsmString, static bool IsAssemblerInstruction(const StringRef &Name, const CodeGenInstruction &CGI, const SmallVectorImpl &Tokens) { - // Ignore psuedo ops. + // Ignore "codegen only" instructions. + if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + return false; + + // Ignore pseudo ops. // - // FIXME: This is a hack. + // FIXME: This is a hack; can we convert these instructions to set the + // "codegen only" bit instead? if (const RecordVal *Form = CGI.TheDef->getValue("Form")) if (Form->getValue()->getAsString() == "Pseudo") return false; - - // Ignore "PHI" node. - // - // FIXME: This is also a hack. - if (Name == "PHI") - return false; // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. // @@ -245,11 +244,8 @@ static bool IsAssemblerInstruction(const StringRef &Name, // // FIXME: Is this true? // - // Also, we ignore instructions which reference the operand multiple times; - // this implies a constraint we would not currently honor. These are - // currently always fake instructions for simplifying codegen. - // - // FIXME: Encode this assumption in the .td, so we can error out here. + // Also, check for instructions which reference the operand multiple times; + // this implies a constraint we would not honor. std::set OperandNames; for (unsigned i = 1, e = Tokens.size(); i < e; ++i) { if (Tokens[i][0] == '$' && @@ -258,18 +254,15 @@ static bool IsAssemblerInstruction(const StringRef &Name, DEBUG({ errs() << "warning: '" << Name << "': " << "ignoring instruction; operand with attribute '" - << Tokens[i] << "', \n"; + << Tokens[i] << "'\n"; }); return false; } if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) { - DEBUG({ - errs() << "warning: '" << Name << "': " - << "ignoring instruction; tied operand '" - << Tokens[i] << "'\n"; - }); - return false; + std::string Err = "'" + Name.str() + "': " + + "invalid assembler instruction; tied operand '" + Tokens[i].str() + "'"; + throw TGError(CGI.TheDef->getLoc(), Err); } }