//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the "Instituto Nokia de Tecnologia" and
-// is distributed under the University of Illinois Open Source
+// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ARMAddressingModes.h"
#include "ARMGenInstrInfo.inc"
#include "ARMMachineFunctionInfo.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
cl::desc("Enable ARM 2-addr to 3-addr conv"));
ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
- : TargetInstrInfo(ARMInsts, sizeof(ARMInsts)/sizeof(ARMInsts[0])),
+ : TargetInstrInfo(ARMInsts, array_lengthof(ARMInsts)),
RI(*this, STI) {
}
default: break;
case ARM::LDR:
if (MI->getOperand(1).isFrameIndex() &&
- MI->getOperand(2).isReg() &&
+ MI->getOperand(2).isRegister() &&
MI->getOperand(3).isImmediate() &&
MI->getOperand(2).getReg() == 0 &&
MI->getOperand(3).getImmedValue() == 0) {
default: break;
case ARM::STR:
if (MI->getOperand(1).isFrameIndex() &&
- MI->getOperand(2).isReg() &&
+ MI->getOperand(2).isRegister() &&
MI->getOperand(3).isImmediate() &&
MI->getOperand(2).getReg() == 0 &&
MI->getOperand(3).getImmedValue() == 0) {
// 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 : {
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;
}
}
// If there is only one terminator instruction, process it.
unsigned LastOpc = LastInst->getOpcode();
- if (I == MBB.begin() ||
- isPredicated(--I) || !isUnpredicatedTerminator(I)) {
+ if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
if (LastOpc == ARM::B || LastOpc == ARM::tB) {
TBB = LastInst->getOperand(0).getMachineBasicBlock();
return false;
// Block ends with fall-through condbranch.
TBB = LastInst->getOperand(0).getMachineBasicBlock();
Cond.push_back(LastInst->getOperand(1));
+ Cond.push_back(LastInst->getOperand(2));
return false;
}
return true; // Can't handle indirect branch.
MachineInstr *SecondLastInst = I;
// If there are three terminators, we don't know what sort of block this is.
- if (SecondLastInst && I != MBB.begin() &&
- !isPredicated(--I) && isUnpredicatedTerminator(I))
+ if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
return true;
// If the block ends with ARM::B/ARM::tB and a ARM::Bcc/ARM::tBcc, handle it.
(SecondLastOpc == ARM::tBcc && LastOpc == ARM::tB)) {
TBB = SecondLastInst->getOperand(0).getMachineBasicBlock();
Cond.push_back(SecondLastInst->getOperand(1));
+ Cond.push_back(SecondLastInst->getOperand(2));
FBB = LastInst->getOperand(0).getMachineBasicBlock();
return false;
}
- // If the block ends with two B's or tB's, handle it. The second one is not
- // executed, so remove it.
+ // If the block ends with two unconditional branches, handle it. The second
+ // one is not executed, so remove it.
if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) &&
(LastOpc == ARM::B || LastOpc == ARM::tB)) {
TBB = SecondLastInst->getOperand(0).getMachineBasicBlock();
return false;
}
+ // Likewise if it ends with a branch table followed by an unconditional branch.
+ // The branch folder can create these, and we must get rid of them for
+ // correctness of Thumb constant islands.
+ if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm ||
+ SecondLastOpc == ARM::BR_JTadd || SecondLastOpc==ARM::tBR_JTr) &&
+ (LastOpc == ARM::B || LastOpc == ARM::tB)) {
+ I = LastInst;
+ I->eraseFromParent();
+ return true;
+ }
+
// Otherwise, can't handle this.
return true;
}
// Shouldn't be a fall through.
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
- assert((Cond.size() == 1 || Cond.size() == 0) &&
+ assert((Cond.size() == 2 || Cond.size() == 0) &&
"ARM branch conditions have two components!");
if (FBB == 0) {
if (Cond.empty()) // Unconditional branch?
BuildMI(&MBB, get(BOpc)).addMBB(TBB);
else
- BuildMI(&MBB, get(BccOpc)).addMBB(TBB).addImm(Cond[0].getImm());
+ BuildMI(&MBB, get(BccOpc)).addMBB(TBB)
+ .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
return 1;
}
// Two-way conditional branch.
- BuildMI(&MBB, get(BccOpc)).addMBB(TBB).addImm(Cond[0].getImm());
+ BuildMI(&MBB, get(BccOpc)).addMBB(TBB)
+ .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
BuildMI(&MBB, get(BOpc)).addMBB(FBB);
return 2;
}
if (Opc == ARM::B || Opc == ARM::tB) {
MI->setInstrDescriptor(get(Opc == ARM::B ? ARM::Bcc : ARM::tBcc));
MI->addImmOperand(Pred[0].getImmedValue());
+ MI->addRegOperand(Pred[1].getReg(), false);
return true;
}
if (PIdx != -1) {
MachineOperand &PMO = MI->getOperand(PIdx);
PMO.setImm(Pred[0].getImmedValue());
+ MI->getOperand(PIdx+1).setReg(Pred[1].getReg());
return true;
}
return false;
bool
ARMInstrInfo::SubsumesPredicate(const std::vector<MachineOperand> &Pred1,
const std::vector<MachineOperand> &Pred2) const{
- if (Pred1.size() > 1 || Pred2.size() > 1)
+ if (Pred1.size() > 2 || Pred2.size() > 2)
return false;
ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImmedValue();
}
}
+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.isRegister() && 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;