mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-02 15:51:54 +00:00
Remove clobbersPred. Add an OptionalDefOperand to instructions which have the 's' bit.
llvm-svn: 38501
This commit is contained in:
parent
0ab209fa54
commit
abcf3842bb
@ -586,8 +586,9 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
||||
CurDAG->getTargetConstant(0, MVT::i32));
|
||||
else {
|
||||
SDOperand Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 4);
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 5);
|
||||
}
|
||||
}
|
||||
case ISD::ADD: {
|
||||
@ -619,10 +620,9 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
||||
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
|
||||
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getTargetConstant(ShImm, MVT::i32),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32)
|
||||
|
||||
};
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 6);
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
|
||||
}
|
||||
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
|
||||
SDOperand V = Op.getOperand(0);
|
||||
@ -631,8 +631,8 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
||||
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getTargetConstant(ShImm, MVT::i32),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
|
||||
};
|
||||
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 6);
|
||||
CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -645,15 +645,17 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
||||
AddToISelQueue(Op.getOperand(0));
|
||||
AddToISelQueue(Op.getOperand(1));
|
||||
SDOperand Ops[] = { Op.getOperand(0), Op.getOperand(1),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, Ops, 4);
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, Ops, 5);
|
||||
}
|
||||
case ARMISD::MULHILOS: {
|
||||
AddToISelQueue(Op.getOperand(0));
|
||||
AddToISelQueue(Op.getOperand(1));
|
||||
SDOperand Ops[] = { Op.getOperand(0), Op.getOperand(1),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, Ops, 4);
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, Ops, 5);
|
||||
}
|
||||
case ISD::LOAD: {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
||||
|
@ -214,15 +214,18 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
// add more than 1 instruction. Abandon!
|
||||
return NULL;
|
||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
||||
.addReg(BaseReg).addImm(SOImmVal).addImm(Pred);
|
||||
.addReg(BaseReg).addImm(SOImmVal)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
} else if (Amt != 0) {
|
||||
ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
|
||||
unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
|
||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc).addImm(Pred);
|
||||
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
} else
|
||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg).addImm(Pred);
|
||||
.addReg(BaseReg).addReg(OffReg)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
break;
|
||||
}
|
||||
case ARMII::AddrMode3 : {
|
||||
@ -231,10 +234,12 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
if (OffReg == 0)
|
||||
// Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
|
||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
||||
.addReg(BaseReg).addImm(Amt).addImm(Pred);
|
||||
.addReg(BaseReg).addImm(Amt)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
else
|
||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg).addImm(Pred);
|
||||
.addReg(BaseReg).addReg(OffReg)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -495,6 +500,25 @@ ARMInstrInfo::SubsumesPredicate(const std::vector<MachineOperand> &Pred1,
|
||||
}
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const {
|
||||
const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
|
||||
if (!TID->ImplicitDefs && (TID->Flags & M_HAS_OPTIONAL_DEF) == 0)
|
||||
return false;
|
||||
|
||||
bool Found = false;
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
if (MO.isReg() && MO.getReg() == ARM::CPSR) {
|
||||
Pred.push_back(MO);
|
||||
Found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Found;
|
||||
}
|
||||
|
||||
|
||||
/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing
|
||||
static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
|
||||
unsigned JTI) DISABLE_INLINE;
|
||||
|
@ -113,6 +113,9 @@ public:
|
||||
virtual
|
||||
bool SubsumesPredicate(const std::vector<MachineOperand> &Pred1,
|
||||
const std::vector<MachineOperand> &Pred1) const;
|
||||
|
||||
virtual bool DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const;
|
||||
};
|
||||
|
||||
// Utility routines
|
||||
|
@ -380,10 +380,25 @@ class I<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
list<Predicate> Predicates = [IsARM];
|
||||
}
|
||||
|
||||
// Same as I except it can optionally modify CPSR.
|
||||
class sI<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
// FIXME: Set all opcodes to 0 for now.
|
||||
: InstARM<0, am, sz, im, cstr> {
|
||||
let OperandList = !con(oprnds, (ops pred:$p, cc_out:$s));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}${s}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsARM];
|
||||
}
|
||||
|
||||
class AI<dag ops, string opc, string asm, list<dag> pattern>
|
||||
: I<ops, AddrModeNone, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||
class AsI<dag ops, string opc, string asm, list<dag> pattern>
|
||||
: sI<ops, AddrModeNone, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||
class AI1<dag ops, string opc, string asm, list<dag> pattern>
|
||||
: I<ops, AddrMode1, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||
class AsI1<dag ops, string opc, string asm, list<dag> pattern>
|
||||
: sI<ops, AddrMode1, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||
class AI2<dag ops, string opc, string asm, list<dag> pattern>
|
||||
: I<ops, AddrMode2, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||
class AI3<dag ops, string opc, string asm, list<dag> pattern>
|
||||
@ -412,21 +427,21 @@ class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
|
||||
|
||||
/// AI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a
|
||||
/// binop that produces a value.
|
||||
multiclass AI1_bin_irs<string opc, PatFrag opnode> {
|
||||
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
multiclass AsI1_bin_irs<string opc, PatFrag opnode> {
|
||||
def ri : AsI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
||||
def rr : AI1<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
def rr : AsI1<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
||||
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
def rs : AsI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
||||
}
|
||||
|
||||
/// AI1_bin_s_irs - Similar to AI1_bin_irs except it sets the 's' bit so the
|
||||
/// ASI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
|
||||
/// instruction modifies the CSPR register.
|
||||
multiclass AI1_bin_s_irs<string opc, PatFrag opnode> {
|
||||
multiclass ASI1_bin_s_irs<string opc, PatFrag opnode> {
|
||||
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
opc, "s $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>, Imp<[], [CPSR]>;
|
||||
@ -439,7 +454,7 @@ multiclass AI1_bin_s_irs<string opc, PatFrag opnode> {
|
||||
}
|
||||
|
||||
/// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
|
||||
/// patterns. Similar to AI1_bin_irs except the instruction does not produce
|
||||
/// patterns. Similar to AsI1_bin_irs except the instruction does not produce
|
||||
/// a explicit result, only implicitly set CPSR.
|
||||
multiclass AI1_cmp_irs<string opc, PatFrag opnode> {
|
||||
def ri : AI1<(ops GPR:$a, so_imm:$b),
|
||||
@ -453,30 +468,6 @@ multiclass AI1_cmp_irs<string opc, PatFrag opnode> {
|
||||
[(opnode GPR:$a, so_reg:$b)]>, Imp<[], [CPSR]>;
|
||||
}
|
||||
|
||||
/// AI1_bin_is - Defines a set of (op r, {so_imm|so_reg}) patterns for a binop.
|
||||
multiclass AI1_bin_is<string opc, PatFrag opnode> {
|
||||
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
||||
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
||||
}
|
||||
|
||||
/// AI1_unary_irs - Defines a set of (op {so_imm|r|so_reg}) patterns for unary
|
||||
/// ops.
|
||||
multiclass AI1_unary_irs<string opc, PatFrag opnode> {
|
||||
def i : AI1<(ops GPR:$dst, so_imm:$a),
|
||||
opc, " $dst, $a",
|
||||
[(set GPR:$dst, (opnode so_imm:$a))]>;
|
||||
def r : AI1<(ops GPR:$dst, GPR:$a),
|
||||
opc, " $dst, $a",
|
||||
[(set GPR:$dst, (opnode GPR:$a))]>;
|
||||
def s : AI1<(ops GPR:$dst, so_reg:$a),
|
||||
opc, " $dst, $a",
|
||||
[(set GPR:$dst, (opnode so_reg:$a))]>;
|
||||
}
|
||||
|
||||
/// AI_unary_rrot - A unary operation with two forms: one whose operand is a
|
||||
/// register and one whose operand is a register rotated by 8/16/24.
|
||||
multiclass AI_unary_rrot<string opc, PatFrag opnode> {
|
||||
@ -536,17 +527,17 @@ class JTI1<dag ops, string asm, list<dag> pattern>
|
||||
class JTI2<dag ops, string asm, list<dag> pattern>
|
||||
: XI<ops, AddrMode2, SizeSpecial, IndexModeNone, asm, "", pattern>;
|
||||
|
||||
/// AXI1_bin_c_irs - Same as AI1_bin_irs but without the predicate operand and
|
||||
/// setting carry bit.
|
||||
multiclass AXI1_bin_c_irs<string opc, PatFrag opnode> {
|
||||
def ri : AXI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
!strconcat(opc, " $dst, $a, $b"),
|
||||
/// AsXI1_bin_c_irs - Same as AsI1_bin_irs but without the predicate operand and
|
||||
/// setting carry bit. But it can optionally set CPSR.
|
||||
multiclass AsXI1_bin_c_irs<string opc, PatFrag opnode> {
|
||||
def ri : AXI1<(ops GPR:$dst, GPR:$a, so_imm:$b, cc_out:$s),
|
||||
!strconcat(opc, "${s} $dst, $a, $b"),
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>, Imp<[CPSR], []>;
|
||||
def rr : AXI1<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
!strconcat(opc, " $dst, $a, $b"),
|
||||
def rr : AXI1<(ops GPR:$dst, GPR:$a, GPR:$b, cc_out:$s),
|
||||
!strconcat(opc, "${s} $dst, $a, $b"),
|
||||
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>, Imp<[CPSR], []>;
|
||||
def rs : AXI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
!strconcat(opc, " $dst, $a, $b"),
|
||||
def rs : AXI1<(ops GPR:$dst, GPR:$a, so_reg:$b, cc_out:$s),
|
||||
!strconcat(opc, "${s} $dst, $a, $b"),
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>, Imp<[CPSR], []>;
|
||||
}
|
||||
|
||||
@ -649,7 +640,7 @@ let isLoad = 1, isReturn = 1, isTerminator = 1 in
|
||||
"ldm${p}${addr:submode} $addr, $dst1",
|
||||
[]>;
|
||||
|
||||
let isCall = 1, noResults = 1, clobbersPred = 1,
|
||||
let isCall = 1, noResults = 1,
|
||||
Defs = [R0, R1, R2, R3, R12, LR,
|
||||
D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in {
|
||||
def BL : AXI<(ops i32imm:$func, variable_ops),
|
||||
@ -697,7 +688,7 @@ let isBranch = 1, isTerminator = 1, noResults = 1 in {
|
||||
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
|
||||
// a two-value operand where a dag node expects two operands. :(
|
||||
def Bcc : AI<(ops brtarget:$dst), "b", " $dst",
|
||||
[/*(ARMbrcond bb:$dst, imm:$cc, CCR:$ccr)*/]>;
|
||||
[/*(ARMbrcond bb:$dst, imm:$cc, CCR:$ccr)*/]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -840,29 +831,28 @@ def STM : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$src1, variable_ops),
|
||||
// Move Instructions.
|
||||
//
|
||||
|
||||
def MOVr : AI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", " $dst, $src", []>;
|
||||
def MOVs : AI1<(ops GPR:$dst, so_reg:$src),
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
|
||||
def MOVr : AsI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", " $dst, $src", []>;
|
||||
def MOVs : AsI1<(ops GPR:$dst, so_reg:$src),
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
|
||||
|
||||
let isReMaterializable = 1 in
|
||||
def MOVi : AI1<(ops GPR:$dst, so_imm:$src),
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
|
||||
def MOVi : AsI1<(ops GPR:$dst, so_imm:$src),
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
|
||||
|
||||
def MOVrx : AsI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", " $dst, $src, rrx",
|
||||
[(set GPR:$dst, (ARMrrx GPR:$src))]>;
|
||||
|
||||
// These aren't really mov instructions, but we have to define them this way
|
||||
// due to flag operands.
|
||||
|
||||
let clobbersPred = 1 in {
|
||||
def MOVsrl_flag : AI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", "s $dst, $src, lsr #1",
|
||||
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, Imp<[], [CPSR]>;
|
||||
def MOVsra_flag : AI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", "s $dst, $src, asr #1",
|
||||
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>, Imp<[], [CPSR]>;
|
||||
}
|
||||
def MOVrx : AI1<(ops GPR:$dst, GPR:$src),
|
||||
"mov", " $dst, $src, rrx",
|
||||
[(set GPR:$dst, (ARMrrx GPR:$src))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extend Instructions.
|
||||
@ -907,38 +897,40 @@ defm UXTAH : AI_bin_rrot<"uxtah",
|
||||
// Arithmetic Instructions.
|
||||
//
|
||||
|
||||
defm ADD : AI1_bin_irs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>>;
|
||||
defm SUB : AI1_bin_irs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
|
||||
defm ADD : AsI1_bin_irs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>>;
|
||||
defm SUB : AsI1_bin_irs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
|
||||
|
||||
// ADD and SUB with 's' bit set.
|
||||
let clobbersPred = 1 in {
|
||||
defm ADDS : AI1_bin_s_irs<"add", BinOpFrag<(addc node:$LHS, node:$RHS)>>;
|
||||
defm SUBS : AI1_bin_s_irs<"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
|
||||
}
|
||||
defm ADDS : ASI1_bin_s_irs<"add", BinOpFrag<(addc node:$LHS, node:$RHS)>>;
|
||||
defm SUBS : ASI1_bin_s_irs<"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
|
||||
|
||||
// FIXME: Do not allow ADC / SBC to be predicated for now.
|
||||
defm ADC : AXI1_bin_c_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
|
||||
defm SBC : AXI1_bin_c_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
|
||||
defm ADC : AsXI1_bin_c_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
|
||||
defm SBC : AsXI1_bin_c_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
|
||||
|
||||
// These don't define reg/reg forms, because they are handled above.
|
||||
defm RSB : AI1_bin_is <"rsb", BinOpFrag<(sub node:$RHS, node:$LHS)>>;
|
||||
def RSBri : AsI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
"rsb", " $dst, $a, $b",
|
||||
[(set GPR:$dst, (sub so_imm:$b, GPR:$a))]>;
|
||||
|
||||
def RSBrs : AsI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
"rsb", " $dst, $a, $b",
|
||||
[(set GPR:$dst, (sub so_reg:$b, GPR:$a))]>;
|
||||
|
||||
// RSB with 's' bit set.
|
||||
let clobbersPred = 1 in {
|
||||
def RSBSri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
"rsb", "s $dst, $a, $b",
|
||||
[(set GPR:$dst, (subc so_imm:$b, GPR:$a))]>, Imp<[], [CPSR]>;
|
||||
def RSBSrs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
"rsb", "s $dst, $a, $b",
|
||||
[(set GPR:$dst, (subc so_reg:$b, GPR:$a))]>, Imp<[], [CPSR]>;
|
||||
}
|
||||
|
||||
// FIXME: Do not allow RSC to be predicated for now.
|
||||
def RSCri : AXI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||
"rsc $dst, $a, $b",
|
||||
// FIXME: Do not allow RSC to be predicated for now. But they can set CPSR.
|
||||
def RSCri : AXI1<(ops GPR:$dst, GPR:$a, so_imm:$b, cc_out:$s),
|
||||
"rsc${s} $dst, $a, $b",
|
||||
[(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>, Imp<[CPSR], []>;
|
||||
def RSCrs : AXI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||
"rsc $dst, $a, $b",
|
||||
def RSCrs : AXI1<(ops GPR:$dst, GPR:$a, so_reg:$b, cc_out:$s),
|
||||
"rsc${s} $dst, $a, $b",
|
||||
[(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>, Imp<[CPSR], []>;
|
||||
|
||||
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
|
||||
@ -961,18 +953,18 @@ def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
|
||||
// Bitwise Instructions.
|
||||
//
|
||||
|
||||
defm AND : AI1_bin_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>>;
|
||||
defm ORR : AI1_bin_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>>;
|
||||
defm EOR : AI1_bin_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
|
||||
defm BIC : AI1_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
|
||||
defm AND : AsI1_bin_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>>;
|
||||
defm ORR : AsI1_bin_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>>;
|
||||
defm EOR : AsI1_bin_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
|
||||
defm BIC : AsI1_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
|
||||
|
||||
def MVNr : AI<(ops GPR:$dst, GPR:$src),
|
||||
"mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
|
||||
def MVNs : AI<(ops GPR:$dst, so_reg:$src),
|
||||
"mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
|
||||
def MVNr : AsI<(ops GPR:$dst, GPR:$src),
|
||||
"mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
|
||||
def MVNs : AsI<(ops GPR:$dst, so_reg:$src),
|
||||
"mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
|
||||
let isReMaterializable = 1 in
|
||||
def MVNi : AI<(ops GPR:$dst, so_imm:$imm),
|
||||
"mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
|
||||
def MVNi : AsI<(ops GPR:$dst, so_imm:$imm),
|
||||
"mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
|
||||
|
||||
def : ARMPat<(and GPR:$src, so_imm_not:$imm),
|
||||
(BICri GPR:$src, so_imm_not:$imm)>;
|
||||
@ -981,46 +973,42 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm),
|
||||
// Multiply Instructions.
|
||||
//
|
||||
|
||||
// AI_orr - Defines a (op r, r) pattern.
|
||||
class AI_orr<string opc, SDNode opnode>
|
||||
: AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
opc, " $dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
||||
def MUL : AsI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
"mul", " $dst, $a, $b",
|
||||
[(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
|
||||
|
||||
// AI_oorr - Defines a (op (op r, r), r) pattern.
|
||||
class AI_oorr<string opc, SDNode opnode1, SDNode opnode2>
|
||||
: AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||
opc, " $dst, $a, $b, $c",
|
||||
[(set GPR:$dst, (opnode1 (opnode2 GPR:$a, GPR:$b), GPR:$c))]>;
|
||||
|
||||
def MUL : AI_orr<"mul", mul>;
|
||||
def MLA : AI_oorr<"mla", add, mul>;
|
||||
def MLA : AsI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||
"mla", " $dst, $a, $b, $c",
|
||||
[(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
|
||||
|
||||
// Extra precision multiplies with low / high results
|
||||
def SMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"smull", " $ldst, $hdst, $a, $b",
|
||||
[]>;
|
||||
def SMULL : AsI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"smull", " $ldst, $hdst, $a, $b", []>;
|
||||
|
||||
def UMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"umull", " $ldst, $hdst, $a, $b",
|
||||
[]>;
|
||||
def UMULL : AsI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"umull", " $ldst, $hdst, $a, $b", []>;
|
||||
|
||||
// Multiply + accumulate
|
||||
def SMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"smlal", " $ldst, $hdst, $a, $b",
|
||||
[]>;
|
||||
def SMLAL : AsI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"smlal", " $ldst, $hdst, $a, $b", []>;
|
||||
|
||||
def UMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"umlal", " $ldst, $hdst, $a, $b",
|
||||
[]>;
|
||||
def UMLAL : AsI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"umlal", " $ldst, $hdst, $a, $b", []>;
|
||||
|
||||
def UMAAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||
"umaal", " $ldst, $hdst, $a, $b",
|
||||
[]>, Requires<[IsARM, HasV6]>;
|
||||
"umaal", " $ldst, $hdst, $a, $b", []>,
|
||||
Requires<[IsARM, HasV6]>;
|
||||
|
||||
// Most significant word multiply
|
||||
def SMMUL : AI_orr<"smmul", mulhs>, Requires<[IsARM, HasV6]>;
|
||||
def SMMLA : AI_oorr<"smmla", add, mulhs>, Requires<[IsARM, HasV6]>;
|
||||
def SMMUL : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||
"smmul", " $dst, $a, $b",
|
||||
[(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>,
|
||||
Requires<[IsARM, HasV6]>;
|
||||
|
||||
def SMMLA : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||
"smmla", " $dst, $a, $b, $c",
|
||||
[(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>,
|
||||
Requires<[IsARM, HasV6]>;
|
||||
|
||||
|
||||
def SMMLS : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||
@ -1164,7 +1152,6 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000),
|
||||
// Comparison Instructions...
|
||||
//
|
||||
|
||||
let clobbersPred = 1 in {
|
||||
defm CMP : AI1_cmp_irs<"cmp", BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
|
||||
defm CMN : AI1_cmp_irs<"cmn", BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
|
||||
|
||||
@ -1174,7 +1161,6 @@ defm TEQ : AI1_cmp_irs<"teq", BinOpFrag<(ARMcmpNZ (xor node:$LHS, node:$RHS), 0
|
||||
|
||||
defm CMPnz : AI1_cmp_irs<"cmp", BinOpFrag<(ARMcmpNZ node:$LHS, node:$RHS)>>;
|
||||
defm CMNnz : AI1_cmp_irs<"cmn", BinOpFrag<(ARMcmpNZ node:$LHS,(ineg node:$RHS))>>;
|
||||
}
|
||||
|
||||
def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
|
||||
(CMNri GPR:$src, so_imm_neg:$imm)>;
|
||||
@ -1223,8 +1209,8 @@ def LEApcrelJT : AXI1<(ops GPR:$dst, i32imm:$label, i32imm:$id, pred:$p),
|
||||
//
|
||||
|
||||
// __aeabi_read_tp preserves the registers r1-r3.
|
||||
let isCall = 1, clobbersPred = 1,
|
||||
Defs = [R0, R12, LR] in {
|
||||
let isCall = 1,
|
||||
Defs = [R0, R12, LR, CPSR] in {
|
||||
def TPsoft : AXI<(ops),
|
||||
"bl __aeabi_read_tp",
|
||||
[(set R0, ARMthread_pointer)]>;
|
||||
|
@ -33,7 +33,6 @@ class ThumbI<dag ops, AddrMode am, SizeFlagVal sz,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
// FIXME: Set all opcodes to 0 for now.
|
||||
: InstARM<0, am, sz, IndexModeNone, cstr> {
|
||||
let clobbersPred = 1;
|
||||
let OperandList = ops;
|
||||
let AsmString = asm;
|
||||
let Pattern = pattern;
|
||||
|
@ -275,7 +275,6 @@ def FMDRR : ADI<(ops DPR:$dst, GPR:$src1, GPR:$src2),
|
||||
|
||||
// FMSRR: GPR -> SPR
|
||||
|
||||
let clobbersPred = 1 in
|
||||
def FMSTAT : ASI<(ops), "fmstat", "", [(arm_fmstat)]>, Imp<[], [CPSR]>;
|
||||
|
||||
// FMXR: GPR -> VFP Sstem reg
|
||||
|
@ -158,7 +158,7 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
|
||||
BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase)
|
||||
.addReg(Base, false, false, BaseKill).addImm(ImmedOffset)
|
||||
.addImm(Pred).addReg(PredReg);
|
||||
.addImm(Pred).addReg(PredReg).addReg(0);
|
||||
Base = NewBase;
|
||||
BaseKill = true; // New base is always killed right its use.
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
BuildMI(MBB, I, TII.get(ARM::tMOVr), DestReg).addReg(SrcReg);
|
||||
else
|
||||
BuildMI(MBB, I, TII.get(ARM::MOVr), DestReg).addReg(SrcReg)
|
||||
.addImm((int64_t)ARMCC::AL).addReg(0);
|
||||
.addImm((int64_t)ARMCC::AL).addReg(0).addReg(0);
|
||||
} else if (RC == ARM::SPRRegisterClass)
|
||||
BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg)
|
||||
.addImm((int64_t)ARMCC::AL).addReg(0);
|
||||
@ -258,6 +258,9 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
||||
switch (Opc) {
|
||||
default: break;
|
||||
case ARM::MOVr: {
|
||||
if (MI->getOperand(4).getReg() == ARM::CPSR)
|
||||
// If it is updating CPSR, then it cannot be foled.
|
||||
break;
|
||||
unsigned Pred = MI->getOperand(2).getImmedValue();
|
||||
unsigned PredReg = MI->getOperand(3).getReg();
|
||||
if (OpNum == 0) { // move -> store
|
||||
@ -454,7 +457,7 @@ void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
// Build the new ADD / SUB.
|
||||
BuildMI(MBB, MBBI, TII.get(isSub ? ARM::SUBri : ARM::ADDri), DestReg)
|
||||
.addReg(BaseReg, false, false, true).addImm(SOImmVal)
|
||||
.addImm((unsigned)Pred).addReg(PredReg, false);
|
||||
.addImm((unsigned)Pred).addReg(PredReg).addReg(0);
|
||||
BaseReg = DestReg;
|
||||
}
|
||||
}
|
||||
@ -1380,7 +1383,7 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MachineInstrBuilder MIB =
|
||||
BuildMI(MBB, MBBI, TII.get(isThumb ? ARM::tADDrSPi : ARM::ADDri),FramePtr)
|
||||
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
||||
if (!isThumb) MIB.addImm(ARMCC::AL).addReg(0);
|
||||
if (!isThumb) MIB.addImm(ARMCC::AL).addReg(0).addReg(0);
|
||||
}
|
||||
|
||||
if (!isThumb) {
|
||||
@ -1496,10 +1499,11 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
hasFP(MF))
|
||||
if (NumBytes)
|
||||
BuildMI(MBB, MBBI, TII.get(ARM::SUBri), ARM::SP).addReg(FramePtr)
|
||||
.addImm(NumBytes).addImm((unsigned)ARMCC::AL).addReg(0);
|
||||
.addImm(NumBytes)
|
||||
.addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
||||
else
|
||||
BuildMI(MBB, MBBI, TII.get(ARM::MOVr), ARM::SP).addReg(FramePtr)
|
||||
.addImm((unsigned)ARMCC::AL).addReg(0);
|
||||
.addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
||||
} else if (NumBytes) {
|
||||
emitSPUpdate(MBB, MBBI, NumBytes, ARMCC::AL, 0, false, TII);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user