From 3bbdcea49abddea69d124e7ef055c9fdaa8d12f6 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Thu, 7 Oct 2010 00:42:42 +0000 Subject: [PATCH] Allow use of the 16-bit literal move instruction in CMOVs for ARM mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115884 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelDAGToDAG.cpp | 18 ++++++++++-------- lib/Target/ARM/ARMInstrInfo.td | 13 +++++++++++++ test/CodeGen/ARM/select-imm.ll | 4 ++-- utils/TableGen/ARMDecoderEmitter.cpp | 14 +++++++------- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index d619564a4f2..a7edf1724ac 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -193,7 +193,7 @@ private: SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag); - SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag); @@ -1521,18 +1521,20 @@ SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, } SDNode *ARMDAGToDAGISel:: -SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, +SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { ConstantSDNode *T = dyn_cast(TrueVal); if (!T) return 0; - if (Pred_so_imm(TrueVal.getNode())) { - SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); + unsigned TrueImm = T->getZExtValue(); + bool isSoImm = Pred_so_imm(TrueVal.getNode()); + if (isSoImm || (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff)) { + SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; - return CurDAG->SelectNodeTo(N, - ARM::MOVCCi, MVT::i32, Ops, 5); + return CurDAG->SelectNodeTo(N, (isSoImm ? ARM::MOVCCi : ARM::MOVCCi16), + MVT::i32, Ops, 5); } return 0; } @@ -1589,10 +1591,10 @@ SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { if (Res) return Res; } else { - SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal, + SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal, CCVal, CCR, InFlag); if (!Res) - Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal, + Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal, ARMCC::getOppositeCondition(CCVal), CCR, InFlag); if (Res) return Res; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 893284ad1c3..95bc1d90254 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2416,6 +2416,9 @@ def BCCZi64 : PseudoInst<(outs), // Conditional moves // FIXME: should be able to write a pattern for ARMcmov, but can't use // a two-value operand where a dag node expects two operands. :( +// FIXME: These should all be pseudo-instructions that get expanded to +// the normal MOV instructions. That would fix the dependency on +// special casing them in tblgen. let neverHasSideEffects = 1 in { def MOVCCr : AI1<0b1101, (outs GPR:$dst), (ins GPR:$false, GPR:$true), DPFrm, IIC_iCMOVr, "mov", "\t$dst, $true", @@ -2433,6 +2436,16 @@ def MOVCCs : AI1<0b1101, (outs GPR:$dst), let Inst{25} = 0; } +def MOVCCi16 : AI1<0b1000, (outs GPR:$dst), (ins GPR:$false, i32imm:$src), + DPFrm, IIC_iMOVi, + "movw", "\t$dst, $src", + []>, + RegConstraint<"$false = $dst">, Requires<[IsARM, HasV6T2]>, + UnaryDP { + let Inst{20} = 0; + let Inst{25} = 1; +} + def MOVCCi : AI1<0b1101, (outs GPR:$dst), (ins GPR:$false, so_imm:$true), DPFrm, IIC_iCMOVi, "mov", "\t$dst, $true", diff --git a/test/CodeGen/ARM/select-imm.ll b/test/CodeGen/ARM/select-imm.ll index 6e15fde045f..66e025e3f52 100644 --- a/test/CodeGen/ARM/select-imm.ll +++ b/test/CodeGen/ARM/select-imm.ll @@ -25,8 +25,8 @@ entry: ; ARM: movle r0, #123 ; T2: t2: -; T2: movw r0, #357 -; T2: movle r0, #123 +; T2: mov r0, #123 +; T2: movwgt r0, #357 %0 = icmp sgt i32 %c, 1 %1 = select i1 %0, i32 357, i32 123 diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index ad96c650be0..ad0d8fba001 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1610,13 +1610,13 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // better off using the generic RSCri and RSCrs instructions. if (Name == "RSCSri" || Name == "RSCSrs") return false; - // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used - // in the compiler to implement conditional moves. We can ignore them in - // favor of their more generic versions of instructions. - // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). - if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || - Name == "FCPYScc" || Name == "FCPYDcc" || - Name == "FNEGScc" || Name == "FNEGDcc") + // MOVCCr, MOVCCs, MOVCCi, MOVCCi16, FCYPScc, FCYPDcc, FNEGScc, and + // FNEGDcc are used in the compiler to implement conditional moves. + // We can ignore them in favor of their more generic versions of + // instructions. See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). + if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || + Name == "MOVCCi16" || Name == "FCPYScc" || Name == "FCPYDcc" || + Name == "FNEGScc" || Name == "FNEGDcc") return false; // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc. -- 2.34.1