From 2b4ea795a23ff9d900b9e1f26c92975ef78db1b6 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 26 Dec 2005 09:11:45 +0000 Subject: [PATCH] Added field noResults to Instruction. Currently tblgen cannot tell which operands in the operand list are results so it assumes the first one is a result. This is bad. Ideally we would fix this by separating results from inputs, e.g. (res R32:$dst), (ops R32:$src1, R32:$src2). But that's a more distruptive change. Adding 'let noResults = 1' is the workaround to tell tblgen that the instruction does not produces a result. It works for now since tblgen does not support instructions which produce multiple results. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25017 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaInstrInfo.td | 10 +++---- lib/Target/IA64/IA64InstrInfo.td | 8 +++--- lib/Target/PowerPC/PPCInstrInfo.td | 19 +++++++------ lib/Target/Sparc/SparcInstrInfo.td | 6 ++-- lib/Target/SparcV8/SparcV8InstrInfo.td | 6 ++-- lib/Target/Target.td | 1 + lib/Target/X86/X86InstrInfo.td | 38 ++++++++++++-------------- utils/TableGen/CodeGenInstruction.h | 1 + utils/TableGen/CodeGenTarget.cpp | 1 + utils/TableGen/DAGISelEmitter.cpp | 5 +--- 10 files changed, 48 insertions(+), 47 deletions(-) diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index 939456fef08..97c9d81f7ad 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -404,14 +404,14 @@ def : Pat<(setune GPRC:$X, GPRC:$Y), (CMPEQi (CMPEQ GPRC:$X, GPRC:$Y), 0)>; def : Pat<(setune GPRC:$X, immUExt8:$Y), (CMPEQi (CMPEQ GPRC:$X, immUExt8:$Y), 0)>; -let isReturn = 1, isTerminator = 1 in +let isReturn = 1, isTerminator = 1, noResults = 1 in def RET : MbrForm< 0x1A, 0x02, (ops GPRC:$RD, GPRC:$RS, s64imm:$DISP), "ret $RD,($RS),$DISP">; //Return from subroutine //DAG Version: -let isReturn = 1, isTerminator = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in +let isReturn = 1, isTerminator = 1, noResults = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in def RETDAG : MbrForm< 0x1A, 0x02, (ops), "ret $$31,($$26),1">; //Return from subroutine def JMP : MbrForm< 0x1A, 0x00, (ops GPRC:$RD, GPRC:$RS, GPRC:$DISP), "jmp $RD,($RS),$DISP">; //Jump -let isCall = 1, Ra = 26, +let isCall = 1, noResults = 1, Ra = 26, Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, F0, F1, @@ -419,7 +419,7 @@ let isCall = 1, Ra = 26, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30], Uses = [R29] in { def BSR : BFormD<0x34, "bsr $$26,$$$DISP..ng", []>; //Branch to subroutine } -let isCall = 1, +let isCall = 1, noResults = 1, Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, F0, F1, @@ -428,7 +428,7 @@ let isCall = 1, def JSR : MbrForm< 0x1A, 0x01, (ops ), "jsr $$26,($$27),0">; //Jump to subroutine } -let isCall = 1, Defs = [R23, R24, R25, R27, R28], Uses = [R24, R25, R27] in +let isCall = 1, noResults = 1, Defs = [R23, R24, R25, R27, R28], Uses = [R24, R25, R27] in def JSRs : MbrForm< 0x1A, 0x01, (ops ), "jsr $$23,($$27),0">; //Jump to div or rem diff --git a/lib/Target/IA64/IA64InstrInfo.td b/lib/Target/IA64/IA64InstrInfo.td index d64682fe865..a38338ffca6 100644 --- a/lib/Target/IA64/IA64InstrInfo.td +++ b/lib/Target/IA64/IA64InstrInfo.td @@ -520,7 +520,7 @@ def CADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s22imm:$imm, PR:$qp), def SUBIMM8 : AForm<0x03, 0x0b, (ops GR:$dst, s8imm:$imm, GR:$src2), "sub $dst = $imm, $src2;;">; -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def ST1 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value), "st1 [$dstPtr] = $value;;">; def ST2 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value), @@ -643,7 +643,7 @@ def FP_TO_UINT : Pat<(i64 (fp_to_uint FP:$src)), (GETFSIG (FCVTFXUTRUNC FP:$src))>; -let isTerminator = 1, isBranch = 1 in { +let isTerminator = 1, isBranch = 1, noResults = 1 in { def BRL_NOTCALL : RawForm<0x03, 0xb0, (ops i64imm:$dst), "(p0) brl.cond.sptk $dst;;">; def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst), @@ -652,7 +652,7 @@ let isTerminator = 1, isBranch = 1 in { "($qp) br.cond.sptk $dst;;">; } -let isCall = 1, /* isTerminator = 1, isBranch = 1, */ +let isCall = 1, noResults = 1, /* isTerminator = 1, isBranch = 1, */ Uses = [out0,out1,out2,out3,out4,out5,out6,out7], // all calls clobber non-callee-saved registers, and for now, they are these: Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24, @@ -688,7 +688,7 @@ let isCall = 1, /* isTerminator = 1, isBranch = 1, */ "($qp) br.cond.call.sptk $dst;;">; } -let isTerminator = 1, isReturn = 1 in +let isTerminator = 1, isReturn = 1, noResults = 1 in def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 55eea5fcd46..2830964c6a9 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -224,17 +224,18 @@ let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. let isTerminator = 1 in { // FIXME: temporary workaround for return without an incoming flag. - let isReturn = 1 in + let isReturn = 1, noResults = 1 in def BLRVOID : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB, [(ret)]>; - let isReturn = 1, hasInFlag = 1 in + let isReturn = 1, noResults = 1, hasInFlag = 1 in def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB, []>; + let noResults = 1 in def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB, []>; } let Defs = [LR] in def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label", []>; -let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, noResults = 1 in { def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc, target:$true, target:$false), "; COND_BRANCH", []>; @@ -262,7 +263,7 @@ let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { "bnu $crS, $block", BrB>; } -let isCall = 1, +let isCall = 1, noResults = 1, // All calls clobber the non-callee saved registers... Defs = [R0,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12, F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13, @@ -328,7 +329,7 @@ def LI : DForm_2_r0<14, (ops GPRC:$rD, symbolLo:$imm), def LIS : DForm_2_r0<15, (ops GPRC:$rD, symbolHi:$imm), "lis $rD, $imm", IntGeneral, [(set GPRC:$rD, imm16Shifted:$imm)]>; -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def STMW : DForm_3<47, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA), "stmw $rS, $disp($rA)", LdStLMW, []>; @@ -385,7 +386,7 @@ def LFD : DForm_8<50, (ops F8RC:$rD, memri:$src), "lfd $rD, $src", LdStLFD, [(set F8RC:$rD, (load iaddr:$src))]>; } -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def STFS : DForm_9<52, (ops F4RC:$rS, memri:$dst), "stfs $rS, $dst", LdStUX, [(store F4RC:$rS, iaddr:$dst)]>; @@ -404,7 +405,7 @@ def LD : DSForm_2<58, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA), "ld $rT, $DS($rA)", LdStLD, []>, isPPC64; } -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def STD : DSForm_2<62, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA), "std $rT, $DS($rA)", LdStSTD, []>, isPPC64; @@ -511,7 +512,7 @@ def SRAD : XForm_6<31, 794, (ops G8RC:$rA, G8RC:$rS, G8RC:$rB), def SRAW : XForm_6<31, 792, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "sraw $rA, $rS, $rB", IntShift, [(set GPRC:$rA, (PPCsra GPRC:$rS, GPRC:$rB))]>; -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def STBX : XForm_8<31, 215, (ops GPRC:$rS, memrr:$dst), "stbx $rS, $dst", LdStGeneral, [(truncstore GPRC:$rS, xaddr:$dst, i8)]>; @@ -636,7 +637,7 @@ def FNEGD : XForm_26<63, 40, (ops F8RC:$frD, F8RC:$frB), [(set F8RC:$frD, (fneg F8RC:$frB))]>; -let isStore = 1 in { +let isStore = 1, noResults = 1 in { def STFIWX: XForm_28<31, 983, (ops F4RC:$frS, memrr:$dst), "stfiwx $frS, $dst", LdStUX, []>; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 79c054eab57..b0fc405d07c 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -171,7 +171,7 @@ let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. // Section A.3 - Synthetic Instructions, p. 85 // special cases of JMPL: -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1 in { +let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, noResults = 1 in { let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in // FIXME: temporary workaround for return without an incoming flag. def RETVOID: F3_2<2, 0b111000, (ops), "retl", [(ret)]>; @@ -466,6 +466,7 @@ class BranchV8 cc, dag ops, string asmstr, list pattern> let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let noResults = 1; } let isBarrier = 1 in @@ -511,6 +512,7 @@ class FPBranchV8 cc, dag ops, string asmstr, list pattern> let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let noResults = 1; } def FBU : FPBranchV8<0b0111, (ops brtarget:$dst), @@ -561,7 +563,7 @@ def FBO : FPBranchV8<0b1111, (ops brtarget:$dst), // Section B.24 - Call and Link Instruction, p. 125 // This is the only Format 1 instruction let Uses = [O0, O1, O2, O3, O4, O5], - hasDelaySlot = 1, isCall = 1, hasInFlag = 1, hasOutFlag = 1, + hasDelaySlot = 1, isCall = 1, hasInFlag = 1, hasOutFlag = 1, noResults = 1, Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in { def CALL : InstV8<(ops calltarget:$dst), diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.td b/lib/Target/SparcV8/SparcV8InstrInfo.td index 79c054eab57..b0fc405d07c 100644 --- a/lib/Target/SparcV8/SparcV8InstrInfo.td +++ b/lib/Target/SparcV8/SparcV8InstrInfo.td @@ -171,7 +171,7 @@ let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. // Section A.3 - Synthetic Instructions, p. 85 // special cases of JMPL: -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1 in { +let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, noResults = 1 in { let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in // FIXME: temporary workaround for return without an incoming flag. def RETVOID: F3_2<2, 0b111000, (ops), "retl", [(ret)]>; @@ -466,6 +466,7 @@ class BranchV8 cc, dag ops, string asmstr, list pattern> let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let noResults = 1; } let isBarrier = 1 in @@ -511,6 +512,7 @@ class FPBranchV8 cc, dag ops, string asmstr, list pattern> let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let noResults = 1; } def FBU : FPBranchV8<0b0111, (ops brtarget:$dst), @@ -561,7 +563,7 @@ def FBO : FPBranchV8<0b1111, (ops brtarget:$dst), // Section B.24 - Call and Link Instruction, p. 125 // This is the only Format 1 instruction let Uses = [O0, O1, O2, O3, O4, O5], - hasDelaySlot = 1, isCall = 1, hasInFlag = 1, hasOutFlag = 1, + hasDelaySlot = 1, isCall = 1, hasInFlag = 1, hasOutFlag = 1, noResults = 1, Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in { def CALL : InstV8<(ops calltarget:$dst), diff --git a/lib/Target/Target.td b/lib/Target/Target.td index f2b98ad4995..4622fe44ba2 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -171,6 +171,7 @@ class Instruction { bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? bit hasInFlag = 0; // Does this instruction read a flag operand? bit hasOutFlag = 0; // Does this instruction write a flag operand? + bit noResults = 0; // Does this instruction produce no results? InstrItinClass Itinerary; // Execution steps used for scheduling. } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index f69162e23f2..edb7285c0d8 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -289,12 +289,15 @@ let isTerminator = 1 in // // Return instructions. -let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in { +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1, noResults = 1 in { // FIXME: temporary workaround for return without an incoming flag. def RETVOID : I<0xC3, RawFrm, (ops), "ret", [(ret)]>; let hasInFlag = 1 in { - def RET : I<0xC3, RawFrm, (ops), "ret", []>; - def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>; + def RET : I<0xC3, RawFrm, (ops), "ret", + [(X86retflag 0)]>; + def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", + [(X86retflag imm:$amt)]>; } } @@ -302,7 +305,7 @@ def : Pat<(X86retflag 0), (RET)>; def : Pat<(X86retflag imm:$amt), (RETI imm:$amt)>; // All branches are RawFrm, Void, Branch, and Terminators -let isBranch = 1, isTerminator = 1 in +let isBranch = 1, isTerminator = 1, noResults = 1 in class IBr opcode, dag ops, string asm, list pattern> : I; @@ -339,7 +342,7 @@ def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst", []>, TB; //===----------------------------------------------------------------------===// // Call Instructions... // -let isCall = 1 in +let isCall = 1, noResults = 1 in // All calls clobber the non-callee saved registers... let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in { @@ -349,11 +352,11 @@ let isCall = 1 in } // Tail call stuff. -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in def TAILJMPd : IBr<0xE9, (ops calltarget:$dst), "jmp $dst # TAIL CALL", []>; -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in def TAILJMPr : I<0xFF, MRM4r, (ops R32:$dst), "jmp {*}$dst # TAIL CALL", []>; -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in def TAILJMPm : I<0xFF, MRM4m, (ops i32mem:$dst), "jmp {*}$dst # TAIL CALL", []>; @@ -2305,20 +2308,13 @@ class FpI pattern> let Pattern = pattern; } -// FpI - Floating Point Psuedo Instruction template. -// TEMPORARY: for FpGETRESULT and FpSETRESULT only. Since -// they must match regardless of X86Vector. -class FpPseudoI pattern> - : X86Inst<0, Pseudo, NoImm, ops, ""> { - let FPForm = fp; let FPFormBits = FPForm.Value; - let Pattern = pattern; -} - // Random Pseudo Instructions. -def FpGETRESULT : FpPseudoI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) -let hasOutFlag = 1 in - def FpSETRESULT : FpPseudoI<(ops RFP:$src), SpecialFP, - [(X86fpset RFP:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR +def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) +let noResults = 1, hasOutFlag = 1 in + def FpSETRESULT : FpI<(ops RFP:$src), SpecialFP, + []>, Imp<[], [ST0]>; // ST(0) = FPR + +def : Pat<(X86fpset RFP:$src), (FpSETRESULT RFP:$src)>; def FpMOV : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, []>; // f1 = fmov f2 diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 703da46804e..b76d3b98694 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -87,6 +87,7 @@ namespace llvm { bool hasCtrlDep; bool hasInFlag; bool hasOutFlag; + bool noResults; CodeGenInstruction(Record *R, const std::string &AsmStr); diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index b6ddd6285c3..25d01fc0553 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -273,6 +273,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) hasCtrlDep = R->getValueAsBit("hasCtrlDep"); hasInFlag = R->getValueAsBit("hasInFlag"); hasOutFlag = R->getValueAsBit("hasOutFlag"); + noResults = R->getValueAsBit("noResults"); hasVariableNumberOfOperands = false; DagInit *DI; diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 8754097d904..85ebfdece9a 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -1097,11 +1097,8 @@ void DAGISelEmitter::ParseInstructions() { CodeGenInstruction &InstInfo =Target.getInstruction(Instrs[i]->getName()); if (InstInfo.OperandList.size() != 0) { - // It's possible for some instruction, e.g. RET for X86 that only has an - // implicit flag operand. // FIXME: temporary hack... - if (InstInfo.isReturn || InstInfo.isBranch || InstInfo.isCall || - InstInfo.isStore) { + if (InstInfo.noResults) { // These produce no results for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j) Operands.push_back(InstInfo.OperandList[j].Rec);