mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-01 07:09:02 +00:00
Add conditional mvn instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118935 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e1634e9351
commit
875a6ac09a
@ -142,14 +142,30 @@ public:
|
|||||||
bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
|
bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
|
||||||
SDValue &OffReg, SDValue &ShImm);
|
SDValue &OffReg, SDValue &ShImm);
|
||||||
|
|
||||||
|
inline bool is_so_imm(unsigned Imm) const {
|
||||||
|
return ARM_AM::getSOImmVal(Imm) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_so_imm_not(unsigned Imm) const {
|
||||||
|
return ARM_AM::getSOImmVal(~Imm) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_t2_so_imm(unsigned Imm) const {
|
||||||
|
return ARM_AM::getT2SOImmVal(Imm) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_t2_so_imm_not(unsigned Imm) const {
|
||||||
|
return ARM_AM::getT2SOImmVal(~Imm) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Pred_so_imm(SDNode *inN) const {
|
inline bool Pred_so_imm(SDNode *inN) const {
|
||||||
ConstantSDNode *N = cast<ConstantSDNode>(inN);
|
ConstantSDNode *N = cast<ConstantSDNode>(inN);
|
||||||
return ARM_AM::getSOImmVal(N->getZExtValue()) != -1;
|
return is_so_imm(N->getZExtValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Pred_t2_so_imm(SDNode *inN) const {
|
inline bool Pred_t2_so_imm(SDNode *inN) const {
|
||||||
ConstantSDNode *N = cast<ConstantSDNode>(inN);
|
ConstantSDNode *N = cast<ConstantSDNode>(inN);
|
||||||
return ARM_AM::getT2SOImmVal(N->getZExtValue()) != -1;
|
return is_t2_so_imm(N->getZExtValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include the pieces autogenerated from the target description.
|
// Include the pieces autogenerated from the target description.
|
||||||
@ -1767,13 +1783,18 @@ SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned TrueImm = T->getZExtValue();
|
unsigned TrueImm = T->getZExtValue();
|
||||||
bool isSoImm = Pred_t2_so_imm(TrueVal.getNode());
|
bool isSoImm = is_t2_so_imm(TrueImm);
|
||||||
if (isSoImm || TrueImm <= 0xffff) {
|
if (isSoImm || TrueImm <= 0xffff) {
|
||||||
SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32);
|
SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
|
||||||
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
||||||
SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
|
SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
|
||||||
return CurDAG->SelectNodeTo(N, (isSoImm ? ARM::t2MOVCCi : ARM::t2MOVCCi16),
|
return CurDAG->SelectNodeTo(N, (isSoImm ? ARM::t2MOVCCi : ARM::t2MOVCCi16),
|
||||||
MVT::i32, Ops, 5);
|
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 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1786,13 +1807,18 @@ SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned TrueImm = T->getZExtValue();
|
unsigned TrueImm = T->getZExtValue();
|
||||||
bool isSoImm = Pred_so_imm(TrueVal.getNode());
|
bool isSoImm = is_so_imm(TrueImm);
|
||||||
if (isSoImm || (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff)) {
|
if (isSoImm || (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff)) {
|
||||||
SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
|
SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
|
||||||
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
||||||
SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
|
SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
|
||||||
return CurDAG->SelectNodeTo(N, (isSoImm ? ARM::MOVCCi : ARM::MOVCCi16),
|
return CurDAG->SelectNodeTo(N, (isSoImm ? ARM::MOVCCi : ARM::MOVCCi16),
|
||||||
MVT::i32, Ops, 5);
|
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 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -212,12 +212,12 @@ def imm16_31 : PatLeaf<(i32 imm), [{
|
|||||||
|
|
||||||
def so_imm_neg :
|
def so_imm_neg :
|
||||||
PatLeaf<(imm), [{
|
PatLeaf<(imm), [{
|
||||||
return ARM_AM::getSOImmVal(-(int)N->getZExtValue()) != -1;
|
return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1;
|
||||||
}], so_imm_neg_XFORM>;
|
}], so_imm_neg_XFORM>;
|
||||||
|
|
||||||
def so_imm_not :
|
def so_imm_not :
|
||||||
PatLeaf<(imm), [{
|
PatLeaf<(imm), [{
|
||||||
return ARM_AM::getSOImmVal(~(int)N->getZExtValue()) != -1;
|
return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1;
|
||||||
}], so_imm_not_XFORM>;
|
}], so_imm_not_XFORM>;
|
||||||
|
|
||||||
// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits.
|
// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits.
|
||||||
@ -2875,6 +2875,7 @@ def BCCZi64 : PseudoInst<(outs),
|
|||||||
// the normal MOV instructions. That would fix the dependency on
|
// the normal MOV instructions. That would fix the dependency on
|
||||||
// special casing them in tblgen.
|
// special casing them in tblgen.
|
||||||
let neverHasSideEffects = 1 in {
|
let neverHasSideEffects = 1 in {
|
||||||
|
let isAsCheapAsAMove = 1 in
|
||||||
def MOVCCr : AI1<0b1101, (outs GPR:$Rd), (ins GPR:$false, GPR:$Rm), DPFrm,
|
def MOVCCr : AI1<0b1101, (outs GPR:$Rd), (ins GPR:$false, GPR:$Rm), DPFrm,
|
||||||
IIC_iCMOVr, "mov", "\t$Rd, $Rm",
|
IIC_iCMOVr, "mov", "\t$Rd, $Rm",
|
||||||
[/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
|
[/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
|
||||||
@ -2903,6 +2904,7 @@ def MOVCCs : AI1<0b1101, (outs GPR:$Rd),
|
|||||||
let Inst{11-0} = shift;
|
let Inst{11-0} = shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isAsCheapAsAMove = 1 in
|
||||||
def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm),
|
def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm),
|
||||||
DPFrm, IIC_iMOVi,
|
DPFrm, IIC_iMOVi,
|
||||||
"movw", "\t$Rd, $imm",
|
"movw", "\t$Rd, $imm",
|
||||||
@ -2918,6 +2920,7 @@ def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm),
|
|||||||
let Inst{11-0} = imm{11-0};
|
let Inst{11-0} = imm{11-0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isAsCheapAsAMove = 1 in
|
||||||
def MOVCCi : AI1<0b1101, (outs GPR:$Rd),
|
def MOVCCi : AI1<0b1101, (outs GPR:$Rd),
|
||||||
(ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi,
|
(ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi,
|
||||||
"mov", "\t$Rd, $imm",
|
"mov", "\t$Rd, $imm",
|
||||||
@ -2931,6 +2934,21 @@ def MOVCCi : AI1<0b1101, (outs GPR:$Rd),
|
|||||||
let Inst{15-12} = Rd;
|
let Inst{15-12} = Rd;
|
||||||
let Inst{11-0} = imm;
|
let Inst{11-0} = imm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isAsCheapAsAMove = 1 in
|
||||||
|
def MVNCCi : AI1<0b1111, (outs GPR:$Rd),
|
||||||
|
(ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi,
|
||||||
|
"mvn", "\t$Rd, $imm",
|
||||||
|
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>,
|
||||||
|
RegConstraint<"$false = $Rd">, UnaryDP {
|
||||||
|
bits<4> Rd;
|
||||||
|
bits<12> imm;
|
||||||
|
let Inst{25} = 1;
|
||||||
|
let Inst{20} = 0;
|
||||||
|
let Inst{19-16} = 0b0000;
|
||||||
|
let Inst{15-12} = Rd;
|
||||||
|
let Inst{11-0} = imm;
|
||||||
|
}
|
||||||
} // neverHasSideEffects
|
} // neverHasSideEffects
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -66,7 +66,7 @@ def t2_so_imm_not : Operand<i32>,
|
|||||||
// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
|
// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
|
||||||
def t2_so_imm_neg : Operand<i32>,
|
def t2_so_imm_neg : Operand<i32>,
|
||||||
PatLeaf<(imm), [{
|
PatLeaf<(imm), [{
|
||||||
return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1;
|
return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1;
|
||||||
}], t2_so_imm_neg_XFORM>;
|
}], t2_so_imm_neg_XFORM>;
|
||||||
|
|
||||||
// Break t2_so_imm's up into two pieces. This handles immediates with up to 16
|
// Break t2_so_imm's up into two pieces. This handles immediates with up to 16
|
||||||
@ -2243,7 +2243,7 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq",
|
|||||||
// Conditional moves
|
// Conditional moves
|
||||||
// FIXME: should be able to write a pattern for ARMcmov, but can't use
|
// 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. :(
|
// a two-value operand where a dag node expects two operands. :(
|
||||||
let neverHasSideEffects = 1 in {
|
let neverHasSideEffects = 1, isAsCheapAsAMove = 1 in {
|
||||||
def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr,
|
def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr,
|
||||||
"mov", ".w\t$dst, $true",
|
"mov", ".w\t$dst, $true",
|
||||||
[/*(set rGPR:$dst, (ARMcmov rGPR:$false, rGPR:$true, imm:$cc, CCR:$ccr))*/]>,
|
[/*(set rGPR:$dst, (ARMcmov rGPR:$false, rGPR:$true, imm:$cc, CCR:$ccr))*/]>,
|
||||||
@ -2270,7 +2270,7 @@ def t2MOVCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true),
|
|||||||
}
|
}
|
||||||
|
|
||||||
def t2MOVCCi16 : T2I<(outs rGPR:$dst), (ins rGPR:$false, i32imm:$src),
|
def t2MOVCCi16 : T2I<(outs rGPR:$dst), (ins rGPR:$false, i32imm:$src),
|
||||||
IIC_iMOVi,
|
IIC_iCMOVi,
|
||||||
"movw", "\t$dst, $src", []>,
|
"movw", "\t$dst, $src", []>,
|
||||||
RegConstraint<"$false = $dst"> {
|
RegConstraint<"$false = $dst"> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
@ -2280,6 +2280,19 @@ def t2MOVCCi16 : T2I<(outs rGPR:$dst), (ins rGPR:$false, i32imm:$src),
|
|||||||
let Inst{15} = 0;
|
let Inst{15} = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
imm:$cc, CCR:$ccr))*/]>,
|
||||||
|
RegConstraint<"$false = $dst"> {
|
||||||
|
let Inst{31-27} = 0b11110;
|
||||||
|
let Inst{25} = 0;
|
||||||
|
let Inst{24-21} = 0b0011;
|
||||||
|
let Inst{20} = 0; // The S bit.
|
||||||
|
let Inst{19-16} = 0b1111; // Rn
|
||||||
|
let Inst{15} = 0;
|
||||||
|
}
|
||||||
|
|
||||||
class T2I_movcc_sh<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
class T2I_movcc_sh<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
||||||
string opc, string asm, list<dag> pattern>
|
string opc, string asm, list<dag> pattern>
|
||||||
: T2I<oops, iops, itin, opc, asm, pattern> {
|
: T2I<oops, iops, itin, opc, asm, pattern> {
|
||||||
|
@ -1,15 +1,59 @@
|
|||||||
; RUN: llc < %s -march=arm | grep mov | count 2
|
; RUN: llc < %s -mtriple=arm-apple-darwin -mcpu=cortex-a8 | FileCheck %s -check-prefix=ARM
|
||||||
|
; RUN: llc < %s -mtriple=thumb-apple-darwin -mcpu=cortex-a8 | FileCheck %s -check-prefix=T2
|
||||||
|
; rdar://8662825
|
||||||
|
|
||||||
define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind {
|
define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind {
|
||||||
%tmp1 = icmp sgt i32 %c, 10
|
; ARM: t1:
|
||||||
%tmp2 = select i1 %tmp1, i32 0, i32 2147483647
|
; ARM: sub r0, r1, #6, 2
|
||||||
%tmp3 = add i32 %tmp2, %b
|
; ARM: movgt r0, r1
|
||||||
ret i32 %tmp3
|
|
||||||
|
; T2: t1:
|
||||||
|
; T2: sub.w r0, r1, #-2147483648
|
||||||
|
; T2: movgt r0, r1
|
||||||
|
%tmp1 = icmp sgt i32 %c, 10
|
||||||
|
%tmp2 = select i1 %tmp1, i32 0, i32 2147483647
|
||||||
|
%tmp3 = add i32 %tmp2, %b
|
||||||
|
ret i32 %tmp3
|
||||||
}
|
}
|
||||||
|
|
||||||
define i32 @t2(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
|
define i32 @t2(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
|
||||||
%tmp1 = icmp sgt i32 %c, 10
|
; ARM: t2:
|
||||||
%tmp2 = select i1 %tmp1, i32 0, i32 10
|
; ARM: sub r0, r1, #10
|
||||||
%tmp3 = sub i32 %b, %tmp2
|
; ARM: movgt r0, r1
|
||||||
ret i32 %tmp3
|
|
||||||
|
; T2: t2:
|
||||||
|
; T2: sub.w r0, r1, #10
|
||||||
|
; T2: movgt r0, r1
|
||||||
|
%tmp1 = icmp sgt i32 %c, 10
|
||||||
|
%tmp2 = select i1 %tmp1, i32 0, i32 10
|
||||||
|
%tmp3 = sub i32 %b, %tmp2
|
||||||
|
ret i32 %tmp3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @t3(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
|
||||||
|
; ARM: t3:
|
||||||
|
; ARM: mvnlt r2, #0
|
||||||
|
; ARM: and r0, r2, r3
|
||||||
|
|
||||||
|
; T2: t3:
|
||||||
|
; T2: movlt.w r2, #-1
|
||||||
|
; T2: and.w r0, r2, r3
|
||||||
|
%cond = icmp slt i32 %a, %b
|
||||||
|
%z = select i1 %cond, i32 -1, i32 %x
|
||||||
|
%s = and i32 %z, %y
|
||||||
|
ret i32 %s
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @t4(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
|
||||||
|
; ARM: t4:
|
||||||
|
; ARM: movlt r2, #0
|
||||||
|
; ARM: orr r0, r2, r3
|
||||||
|
|
||||||
|
; T2: t4:
|
||||||
|
; T2: movlt r2, #0
|
||||||
|
; T2: orr.w r0, r2, r3
|
||||||
|
%cond = icmp slt i32 %a, %b
|
||||||
|
%z = select i1 %cond, i32 0, i32 %x
|
||||||
|
%s = or i32 %z, %y
|
||||||
|
ret i32 %s
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user