From 90b7b12f012d9234488277a323231e0b7a8d12ac Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 18 Oct 2011 19:18:52 +0000 Subject: [PATCH] Use ARM/t2PseudoInst class from ARM/Thumb2 special adds/subs patterns. Clean up the patterns, fix comments, and avoid confusing both tools and coders. Note that the special adds/subs SelectionDAG nodes no longer have the dummy cc_out operand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142397 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/Target.td | 9 ++ lib/Target/ARM/ARMBaseInstrInfo.cpp | 1 - lib/Target/ARM/ARMISelLowering.cpp | 22 +++-- lib/Target/ARM/ARMInstrInfo.td | 130 +++++++++++++--------------- lib/Target/ARM/ARMInstrThumb2.td | 84 +++++++++--------- 5 files changed, 124 insertions(+), 122 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 6e28f796943..9714172aa49 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -356,6 +356,15 @@ class Instruction { // associated with them. Once we've migrated all of them over to true // pseudo-instructions that are lowered to real instructions prior to // the printer/emitter, we can remove this attribute and just use isPseudo. + // + // The intended use is: + // isPseudo: Does not have encoding information and should be expanded, + // at the latest, during lowering to MCInst. + // + // isCodeGenOnly: Does have encoding information and can go through to the + // CodeEmitter unchanged, but duplicates a canonical instruction + // definition's encoding and should be ignored when constructing the + // assembler match tables. bit isCodeGenOnly = 0; // Is this instruction a pseudo instruction for use by the assembler parser. diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 408edfc20d4..24cd228279c 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1478,7 +1478,6 @@ static AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = { {ARM::SUBSrsr, ARM::SUBrsr}, {ARM::RSBSri, ARM::RSBri}, - {ARM::RSBSrr, ARM::RSBrr}, {ARM::RSBSrsi, ARM::RSBrsi}, {ARM::RSBSrsr, ARM::RSBrsr}, diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 04b91398156..ac194145e0f 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6319,8 +6319,8 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const { - const MCInstrDesc &MCID = MI->getDesc(); - if (!MCID.hasPostISelHook()) { + const MCInstrDesc *MCID = &MI->getDesc(); + if (!MCID->hasPostISelHook()) { assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && "Pseudo flag-setting opcodes must be marked with 'hasPostISelHook'"); return; @@ -6331,20 +6331,28 @@ void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, // operand is still set to noreg. If needed, set the optional operand's // register to CPSR, and remove the redundant implicit def. // - // e.g. ADCS (...opt:%noreg, CPSR) -> ADC (... opt:CPSR). + // e.g. ADCS (..., CPSR) -> ADC (... opt:CPSR). // Rename pseudo opcodes. unsigned NewOpc = convertAddSubFlagsOpcode(MI->getOpcode()); if (NewOpc) { const ARMBaseInstrInfo *TII = static_cast(getTargetMachine().getInstrInfo()); - MI->setDesc(TII->get(NewOpc)); + MCID = &TII->get(NewOpc); + + assert(MCID->getNumOperands() == MI->getDesc().getNumOperands() + 1 && + "converted opcode should be the same except for cc_out"); + + MI->setDesc(*MCID); + + // Add the optional cc_out operand + MI->addOperand(MachineOperand::CreateReg(0, /*isDef=*/true)); } - unsigned ccOutIdx = MCID.getNumOperands() - 1; + unsigned ccOutIdx = MCID->getNumOperands() - 1; // Any ARM instruction that sets the 's' bit should specify an optional // "cc_out" operand in the last operand position. - if (!MCID.hasOptionalDef() || !MCID.OpInfo[ccOutIdx].isOptionalDef()) { + if (!MCID->hasOptionalDef() || !MCID->OpInfo[ccOutIdx].isOptionalDef()) { assert(!NewOpc && "Optional cc_out operand required"); return; } @@ -6352,7 +6360,7 @@ void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, // since we already have an optional CPSR def. bool definesCPSR = false; bool deadCPSR = false; - for (unsigned i = MCID.getNumOperands(), e = MI->getNumOperands(); + for (unsigned i = MCID->getNumOperands(), e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) { diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index b509110d0bd..b9cbc83f217 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1040,69 +1040,58 @@ multiclass AsI1_rbin_irs opcod, string opc, } -/// AsI1_rbin_s_is - Same as AsI1_rbin_s_is except it sets 's' bit by default. -/// -/// These opcodes will be converted to the real non-S opcodes by -/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. -let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { -multiclass AsI1_rbin_s_is opcod, string opc, - InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { - def ri : AsI1; - - def rr : AsI1; - - def rsi : AsI1; - - def rsr : AsI1 { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{25} = 0; - let Inst{19-16} = Rn; - let Inst{15-12} = Rd; - let Inst{11-8} = shift{11-8}; - let Inst{7} = 0; - let Inst{6-5} = shift{6-5}; - let Inst{4} = 1; - let Inst{3-0} = shift{3-0}; - } -} -} - /// AsI1_bin_s_irs - Same as AsI1_bin_irs except it sets the 's' bit by default. /// /// These opcodes will be converted to the real non-S opcodes by -/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. -let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { -multiclass AsI1_bin_s_irs opcod, string opc, - InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { - def ri : AsI1; - def rr : AsI1; - def rsi : AsI1; +/// AdjustInstrPostInstrSelection after giving them an optional CPSR operand. +let hasPostISelHook = 1, Defs = [CPSR] in { +multiclass AsI1_bin_s_irs { + def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p), + 4, iii, + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm))]>; - def rsr : AsI1; + def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, pred:$p), + 4, iir, + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm))]> { + let isCommutable = Commutable; + } + def rsi : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$Rn, so_reg_imm:$shift, pred:$p), + 4, iis, + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, + so_reg_imm:$shift))]>; + + def rsr : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$Rn, so_reg_reg:$shift, pred:$p), + 4, iis, + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, + so_reg_reg:$shift))]>; +} +} + +/// AsI1_rbin_s_is - Same as AsI1_bin_s_irs, except selection DAG +/// operands are reversed. +let hasPostISelHook = 1, Defs = [CPSR] in { +multiclass AsI1_rbin_s_is { + def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p), + 4, iii, + [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn))]>; + + def rsi : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$Rn, so_reg_imm:$shift, pred:$p), + 4, iis, + [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, + GPR:$Rn))]>; + + def rsr : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$Rn, so_reg_reg:$shift, pred:$p), + 4, iis, + [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift, + GPR:$Rn))]>; } } @@ -2859,7 +2848,7 @@ def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr, let Inst{15-12} = Rd; } -def : ARMInstAlias<"movs${p} $Rd, $Rm", +def : ARMInstAlias<"movs${p} $Rd, $Rm", (MOVr GPR:$Rd, GPR:$Rm, pred:$p, CPSR)>; // A version for the smaller set of tail call registers. @@ -3079,20 +3068,18 @@ defm SUB : AsI1_bin_irs<0b0010, "sub", // ADD and SUB with 's' bit set. // -// Currently, t2ADDS/t2SUBS are pseudo opcodes that exist only in the -// selection DAG. They are "lowered" to real t2ADD/t2SUB opcodes by +// Currently, ADDS/SUBS are pseudo opcodes that exist only in the +// selection DAG. They are "lowered" to real ADD/SUB opcodes by // AdjustInstrPostInstrSelection where we determine whether or not to // set the "s" bit based on CPSR liveness. // -// FIXME: Eliminate t2ADDS/t2SUBS pseudo opcodes after adding tablegen +// FIXME: Eliminate ADDS/SUBS pseudo opcodes after adding tablegen // support for an optional CPSR definition that corresponds to the DAG // node's second value. We can then eliminate the implicit def of CPSR. -defm ADDS : AsI1_bin_s_irs<0b0100, "add", - IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>; -defm SUBS : AsI1_bin_s_irs<0b0010, "sub", - IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>; +defm ADDS : AsI1_bin_s_irs, 1>; +defm SUBS : AsI1_bin_s_irs>; defm ADC : AI1_adde_sube_irs<0b0101, "adc", BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, @@ -3107,9 +3094,8 @@ defm RSB : AsI1_rbin_irs <0b0011, "rsb", // FIXME: Eliminate them if we can write def : Pat patterns which defines // CPSR and the implicit def of CPSR is not needed. -defm RSBS : AsI1_rbin_s_is<0b0011, "rsb", - IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>; +defm RSBS : AsI1_rbin_s_is>; defm RSC : AI1_rsc_irs<0b0111, "rsc", BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 403d7bc608f..9d8505544d2 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -608,25 +608,48 @@ multiclass T2I_rbin_irs opcod, string opc, PatFrag opnode> { /// /// These opcodes will be converted to the real non-S opcodes by /// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. -let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { -multiclass T2I_bin_s_irs opcod, string opc, - InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { +let hasPostISelHook = 1, Defs = [CPSR] in { +multiclass T2I_bin_s_irs { // shifted imm - def ri : T2sTwoRegImm< - (outs rGPR:$Rd), (ins GPRnopc:$Rn, t2_so_imm:$imm), iii, - opc, ".w\t$Rd, $Rn, $imm", - [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, t2_so_imm:$imm))]>; + def ri : t2PseudoInst<(outs rGPR:$Rd), + (ins GPRnopc:$Rn, t2_so_imm:$imm, pred:$p), + 4, iii, + [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, + t2_so_imm:$imm))]>; // register - def rr : T2sThreeReg< - (outs rGPR:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm), iir, - opc, ".w\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, rGPR:$Rm))]>; + def rr : t2PseudoInst<(outs rGPR:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm, pred:$p), + 4, iir, + [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, + rGPR:$Rm))]> { + let isCommutable = Commutable; + } // shifted register - def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), iis, - opc, ".w\t$Rd, $Rn, $ShiftedRm", - [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm))]>; + def rs : t2PseudoInst<(outs rGPR:$Rd), + (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm, pred:$p), + 4, iis, + [(set rGPR:$Rd, CPSR, (opnode GPRnopc:$Rn, + t2_so_reg:$ShiftedRm))]>; +} +} + +/// T2I_rbin_s_is - Same as T2I_bin_s_irs, except selection DAG +/// operands are reversed. +let hasPostISelHook = 1, Defs = [CPSR] in { +multiclass T2I_rbin_s_is { + // shifted imm + def ri : t2PseudoInst<(outs rGPR:$Rd), + (ins GPRnopc:$Rn, t2_so_imm:$imm, pred:$p), + 4, IIC_iALUi, + [(set rGPR:$Rd, CPSR, (opnode t2_so_imm:$imm, + GPRnopc:$Rn))]>; + // shifted register + def rs : t2PseudoInst<(outs rGPR:$Rd), + (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm, pred:$p), + 4, IIC_iALUsi, + [(set rGPR:$Rd, CPSR, (opnode t2_so_reg:$ShiftedRm, + GPRnopc:$Rn))]>; } } @@ -735,26 +758,6 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, } } -/// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register -/// version is not needed since this is only for codegen. -/// -/// These opcodes will be converted to the real non-S opcodes by -/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. -let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { -multiclass T2I_rbin_s_is opcod, string opc, PatFrag opnode> { - // shifted imm - def ri : T2sTwoRegImm< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi, - opc, ".w\t$Rd, $Rn, $imm", - [(set rGPR:$Rd, CPSR, (opnode t2_so_imm:$imm, rGPR:$Rn))]>; - // shifted register - def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), - IIC_iALUsi, opc, "\t$Rd, $Rn, $ShiftedRm", - [(set rGPR:$Rd, CPSR, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]>; -} -} - /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift / // rotate operation that produces a value. multiclass T2I_sh_ir opcod, string opc, Operand ty, PatFrag opnode, @@ -1845,11 +1848,9 @@ defm t2SUB : T2I_bin_ii12rs<0b101, "sub", // FIXME: Eliminate t2ADDS/t2SUBS pseudo opcodes after adding tablegen // support for an optional CPSR definition that corresponds to the DAG // node's second value. We can then eliminate the implicit def of CPSR. -defm t2ADDS : T2I_bin_s_irs <0b1000, "add", - IIC_iALUi, IIC_iALUr, IIC_iALUsi, +defm t2ADDS : T2I_bin_s_irs , 1>; -defm t2SUBS : T2I_bin_s_irs <0b1101, "sub", - IIC_iALUi, IIC_iALUr, IIC_iALUsi, +defm t2SUBS : T2I_bin_s_irs >; let hasPostISelHook = 1 in { @@ -1865,8 +1866,7 @@ defm t2RSB : T2I_rbin_irs <0b1110, "rsb", // FIXME: Eliminate them if we can write def : Pat patterns which defines // CPSR and the implicit def of CPSR is not needed. -defm t2RSBS : T2I_rbin_s_is <0b1110, "rsb", - BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>; +defm t2RSBS : T2I_rbin_s_is >; // (sub X, imm) gets canonicalized to (add X, -imm). Match this form. // The assume-no-carry-in form uses the negation of the input since add/sub