From 63f3544a7f6ca09e7515d6b0e1bf9e8e884131e2 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 13 Nov 2010 02:25:14 +0000 Subject: [PATCH] Add conditional move of large immediate. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118968 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 10 ++++-- lib/Target/ARM/ARMISelDAGToDAG.cpp | 40 +++++++++++++-------- lib/Target/ARM/ARMInstrInfo.td | 5 +++ lib/Target/ARM/ARMInstrThumb2.td | 10 +++++- test/CodeGen/ARM/select-imm.ll | 47 +++++++++++++++++-------- 5 files changed, 79 insertions(+), 33 deletions(-) diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index b252fd248b2..f38c452fce1 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -691,15 +691,19 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { } case ARM::MOVi32imm: - case ARM::t2MOVi32imm: { + case ARM::MOVCCi32imm: + case ARM::t2MOVi32imm: + case ARM::t2MOVCCi32imm: { unsigned PredReg = 0; ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); unsigned DstReg = MI.getOperand(0).getReg(); bool DstIsDead = MI.getOperand(0).isDead(); - const MachineOperand &MO = MI.getOperand(1); + bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm; + const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1); MachineInstrBuilder LO16, HI16; - if (Opcode == ARM::MOVi32imm && !STI->hasV6T2Ops()) { + if (!STI->hasV6T2Ops() && + (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) { // Expand into a movi + orr. LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg); HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri)) diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index f30fd94a8e1..b5ef7b1a879 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -1782,20 +1782,26 @@ SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, if (!T) return 0; + unsigned Opc = 0; unsigned TrueImm = T->getZExtValue(); bool isSoImm = is_t2_so_imm(TrueImm); if (isSoImm || TrueImm <= 0xffff) { + Opc = isSoImm ? ARM::t2MOVCCi : ARM::t2MOVCCi16; + } else if (is_t2_so_imm_not(TrueImm)) { + TrueImm = ~TrueImm; + Opc = ARM::t2MVNCCi; + } else if (Subtarget->hasV6T2Ops()) { + // Large immediate. + Opc = ARM::t2MOVCCi32imm; + } + + if (Opc) { 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, (isSoImm ? ARM::t2MOVCCi : ARM::t2MOVCCi16), - MVT::i32, Ops, 5); - } else if (is_t2_so_imm_not(TrueImm)) { - 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::t2MVNCCi, MVT::i32, Ops, 5); + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); } + return 0; } @@ -1806,20 +1812,26 @@ SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, if (!T) return 0; + unsigned Opc = 0; unsigned TrueImm = T->getZExtValue(); bool isSoImm = is_so_imm(TrueImm); if (isSoImm || (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff)) { + Opc = isSoImm ? ARM::MOVCCi : ARM::MOVCCi16; + } else if (is_so_imm_not(TrueImm)) { + TrueImm = ~TrueImm; + Opc = ARM::MVNCCi; + } else if (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm)) { + // Large immediate. + Opc = ARM::MOVCCi32imm; + } + + if (Opc) { 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, (isSoImm ? ARM::MOVCCi : ARM::MOVCCi16), - MVT::i32, Ops, 5); - } else if (is_so_imm_not(TrueImm)) { - 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::MVNCCi, MVT::i32, Ops, 5); + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); } + return 0; } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index a0c7c9c5fc2..1e48108e2a5 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2942,6 +2942,11 @@ def MOVCCi : AI1<0b1101, (outs GPR:$Rd), let Inst{11-0} = imm; } +// Two instruction predicate mov immediate. +def MOVCCi32imm : PseudoInst<(outs GPR:$Rd), + (ins GPR:$false, i32imm:$src, pred:$p), + IIC_iMOVix2, "", []>, RegConstraint<"$false = $Rd">; + let isAsCheapAsAMove = 1 in def MVNCCi : AI1<0b1111, (outs GPR:$Rd), (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 66f2259dbf3..6fd814af2ec 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2243,7 +2243,8 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // 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. :( -let neverHasSideEffects = 1, isAsCheapAsAMove = 1 in { +let neverHasSideEffects = 1 in { +let isAsCheapAsAMove = 1 in def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr, "mov", ".w\t$dst, $true", [/*(set rGPR:$dst, (ARMcmov rGPR:$false, rGPR:$true, imm:$cc, CCR:$ccr))*/]>, @@ -2257,6 +2258,7 @@ def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr, let Inst{7-4} = 0b0000; } +let isAsCheapAsAMove = 1 in def t2MOVCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), IIC_iCMOVi, "mov", ".w\t$dst, $true", [/*(set rGPR:$dst,(ARMcmov rGPR:$false,t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>, @@ -2269,6 +2271,7 @@ def t2MOVCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), let Inst{15} = 0; } +let isAsCheapAsAMove = 1 in def t2MOVCCi16 : T2I<(outs rGPR:$dst), (ins rGPR:$false, i32imm:$src), IIC_iCMOVi, "movw", "\t$dst, $src", []>, @@ -2280,6 +2283,11 @@ def t2MOVCCi16 : T2I<(outs rGPR:$dst), (ins rGPR:$false, i32imm:$src), let Inst{15} = 0; } +def t2MOVCCi32imm : PseudoInst<(outs rGPR:$dst), + (ins rGPR:$false, i32imm:$src, pred:$p), + IIC_iMOVix2, "", []>, RegConstraint<"$false = $dst">; + +let isAsCheapAsAMove = 1 in def t2MVNCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), IIC_iCMOVi, "mvn", ".w\t$dst, $true", [/*(set rGPR:$dst,(ARMcmov rGPR:$false,t2_so_imm_not:$true, diff --git a/test/CodeGen/ARM/select-imm.ll b/test/CodeGen/ARM/select-imm.ll index 1dec8f9d04b..578834ec93b 100644 --- a/test/CodeGen/ARM/select-imm.ll +++ b/test/CodeGen/ARM/select-imm.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -march=arm | FileCheck %s --check-prefix=ARM -; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s --check-prefix=T2 +; RUN: llc < %s -march=arm -mattr=+thumb2 | FileCheck %s --check-prefix=ARMT2 +; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s --check-prefix=THUMB2 define i32 @t1(i32 %c) nounwind readnone { entry: @@ -8,9 +9,13 @@ entry: ; ARM: orr r1, r1, #1, 24 ; ARM: movgt r0, #123 -; T2: t1: -; T2: movw r0, #357 -; T2: movgt r0, #123 +; ARMT2: t1: +; ARMT2: movw r0, #357 +; ARMT2: movgt r0, #123 + +; THUMB2: t1: +; THUMB2: movw r0, #357 +; THUMB2: movgt r0, #123 %0 = icmp sgt i32 %c, 1 %1 = select i1 %0, i32 123, i32 357 @@ -20,13 +25,17 @@ entry: define i32 @t2(i32 %c) nounwind readnone { entry: ; ARM: t2: -; ARM: mov r1, #101 -; ARM: orr r1, r1, #1, 24 -; ARM: movle r0, #123 +; ARM: mov r0, #123 +; ARM: movgt r0, #101 +; ARM: orrgt r0, r0, #1, 24 -; T2: t2: -; T2: mov.w r0, #123 -; T2: movwgt r0, #357 +; ARMT2: t2: +; ARMT2: mov r0, #123 +; ARMT2: movwgt r0, #357 + +; THUMB2: t2: +; THUMB2: mov.w r0, #123 +; THUMB2: movwgt r0, #357 %0 = icmp sgt i32 %c, 1 %1 = select i1 %0, i32 357, i32 123 @@ -39,9 +48,13 @@ entry: ; ARM: mov r0, #0 ; ARM: moveq r0, #1 -; T2: t3: -; T2: mov.w r0, #0 -; T2: moveq r0, #1 +; ARMT2: t3: +; ARMT2: mov r0, #0 +; ARMT2: moveq r0, #1 + +; THUMB2: t3: +; THUMB2: mov.w r0, #0 +; THUMB2: moveq r0, #1 %0 = icmp eq i32 %a, 160 %1 = zext i1 %0 to i32 ret i32 %1 @@ -53,8 +66,12 @@ entry: ; ARM: ldr ; ARM: movlt -; T2: t4: -; T2: mvnlt.w r0, #11141290 +; ARMT2: t4: +; ARMT2: movwlt r0, #65365 +; ARMT2: movtlt r0, #65365 + +; THUMB2: t4: +; THUMB2: mvnlt.w r0, #11141290 %0 = icmp slt i32 %a, %b %1 = select i1 %0, i32 4283826005, i32 %x ret i32 %1