summaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-06-27 10:44:33 +0000
committered <ed@FreeBSD.org>2009-06-27 10:44:33 +0000
commitcf5cd875b51255602afaed29deb636b66b295671 (patch)
tree9794dc36f22f2a2b3f8063829d8a9b3a7794acc8 /lib/Target
parent5c1b5c146f3df07c75174aff06c3bb0968f6857e (diff)
downloadFreeBSD-src-cf5cd875b51255602afaed29deb636b66b295671.zip
FreeBSD-src-cf5cd875b51255602afaed29deb636b66b295671.tar.gz
Import LLVM r74383.
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/ARM.h18
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp4
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp53
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp2
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td73
-rw-r--r--lib/Target/ARM/ARMInstrInfo.cpp267
-rw-r--r--lib/Target/ARM/ARMInstrInfo.h110
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td135
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td281
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td444
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.cpp4
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.h6
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp102
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h63
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp128
-rw-r--r--lib/Target/ARM/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/ARM/CMakeLists.txt1
-rw-r--r--lib/Target/ARM/README.txt52
-rw-r--r--lib/Target/ARM/ThumbInstrInfo.cpp282
-rw-r--r--lib/Target/ARM/ThumbInstrInfo.h85
-rw-r--r--lib/Target/Alpha/AlphaJITInfo.cpp6
-rw-r--r--lib/Target/Alpha/AlphaJITInfo.h5
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.cpp4
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.h3
-rw-r--r--lib/Target/Alpha/AlphaTargetMachine.cpp6
-rw-r--r--lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp18
-rw-r--r--lib/Target/Alpha/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/CBackend/CBackend.cpp15
-rw-r--r--lib/Target/CellSPU/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp22
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.cpp6
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp14
-rw-r--r--lib/Target/IA64/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp10
-rw-r--r--lib/Target/IA64/IA64TargetMachine.cpp6
-rw-r--r--lib/Target/MSIL/MSILWriter.cpp6
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp6
-rw-r--r--lib/Target/Mips/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp10
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp6
-rw-r--r--lib/Target/PIC16/PIC16DebugInfo.cpp2
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.cpp29
-rw-r--r--lib/Target/PIC16/PIC16MemSelOpt.cpp10
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.cpp6
-rw-r--r--lib/Target/PowerPC/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp61
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp6
-rw-r--r--lib/Target/Sparc/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp14
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp6
-rw-r--r--lib/Target/X86/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp491
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h23
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp6
-rw-r--r--lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp7
-rw-r--r--lib/Target/X86/X86.td10
-rw-r--r--lib/Target/X86/X86CodeEmitter.cpp8
-rw-r--r--lib/Target/X86/X86FastISel.cpp37
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp188
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp232
-rw-r--r--lib/Target/X86/X86Instr64bit.td23
-rw-r--r--lib/Target/X86/X86InstrBuilder.h4
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp46
-rw-r--r--lib/Target/X86/X86InstrInfo.h81
-rw-r--r--lib/Target/X86/X86InstrInfo.td10
-rw-r--r--lib/Target/X86/X86InstrMMX.td4
-rw-r--r--lib/Target/X86/X86RegisterInfo.td6
-rw-r--r--lib/Target/X86/X86Subtarget.cpp9
-rw-r--r--lib/Target/X86/X86Subtarget.h18
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp17
-rw-r--r--lib/Target/X86/X86TargetMachine.h6
-rw-r--r--lib/Target/XCore/XCoreAsmPrinter.cpp32
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp6
73 files changed, 2135 insertions, 1524 deletions
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index 7edd118..8bf1b7c 100644
--- a/lib/Target/ARM/ARM.h
+++ b/lib/Target/ARM/ARM.h
@@ -20,7 +20,7 @@
namespace llvm {
-class ARMTargetMachine;
+class ARMBaseTargetMachine;
class FunctionPass;
class MachineCodeEmitter;
class JITCodeEmitter;
@@ -28,8 +28,8 @@ class raw_ostream;
// Enums corresponding to ARM condition codes
namespace ARMCC {
- // The CondCodes constants map directly to the 4-bit encoding of the
- // condition field for predicated instructions.
+ // The CondCodes constants map directly to the 4-bit encoding of the
+ // condition field for predicated instructions.
enum CondCodes {
EQ,
NE,
@@ -47,7 +47,7 @@ namespace ARMCC {
LE,
AL
};
-
+
inline static CondCodes getOppositeCondition(CondCodes CC){
switch (CC) {
default: assert(0 && "Unknown condition code");
@@ -90,17 +90,17 @@ inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
}
}
-FunctionPass *createARMISelDag(ARMTargetMachine &TM);
+FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM);
FunctionPass *createARMCodePrinterPass(raw_ostream &O,
- ARMTargetMachine &TM,
+ ARMBaseTargetMachine &TM,
CodeGenOpt::Level OptLevel,
bool Verbose);
-FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
+FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
MachineCodeEmitter &MCE);
-FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
+FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
MachineCodeEmitter &MCE);
-FunctionPass *createARMJITCodeEmitterPass(ARMTargetMachine &TM,
+FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
JITCodeEmitter &JCE);
FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index f6629fe..8424c2e 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -176,11 +176,11 @@ namespace {
namespace llvm {
-FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
+FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
MachineCodeEmitter &MCE) {
return new Emitter<MachineCodeEmitter>(TM, MCE);
}
-FunctionPass *createARMJITCodeEmitterPass(ARMTargetMachine &TM,
+FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
JITCodeEmitter &JCE) {
return new Emitter<JITCodeEmitter>(TM, JCE);
}
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index be543a9..200371b 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -41,14 +41,14 @@ static const unsigned arm_dsubreg_1 = 6;
///
namespace {
class ARMDAGToDAGISel : public SelectionDAGISel {
- ARMTargetMachine &TM;
+ ARMBaseTargetMachine &TM;
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when generating code for different targets.
const ARMSubtarget *Subtarget;
public:
- explicit ARMDAGToDAGISel(ARMTargetMachine &tm)
+ explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm)
: SelectionDAGISel(tm), TM(tm),
Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
}
@@ -92,11 +92,10 @@ public:
bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
SDValue &OffImm);
- bool SelectThumb2ShifterOperandReg(SDValue Op, SDValue N,
- SDValue &BaseReg, SDValue &Opc);
-
bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
SDValue &B, SDValue &C);
+ bool SelectT2ShifterOperandReg(SDValue Op, SDValue N,
+ SDValue &BaseReg, SDValue &Opc);
// Include the pieces autogenerated from the target description.
#include "ARMGenDAGISel.inc"
@@ -520,28 +519,6 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N,
return false;
}
-bool ARMDAGToDAGISel::SelectThumb2ShifterOperandReg(SDValue Op,
- SDValue N,
- SDValue &BaseReg,
- SDValue &Opc) {
- ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
-
- // Don't match base register only case. That is matched to a separate
- // lower complexity pattern with explicit register operand.
- if (ShOpcVal == ARM_AM::no_shift) return false;
-
- BaseReg = N.getOperand(0);
- unsigned ShImmVal = 0;
- if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)))
- ShImmVal = RHS->getZExtValue() & 31;
- else
- return false;
-
- Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
-
- return true;
-}
-
bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
SDValue N,
SDValue &BaseReg,
@@ -566,6 +543,26 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
return true;
}
+bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N,
+ SDValue &BaseReg,
+ SDValue &Opc) {
+ ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
+
+ // Don't match base register only case. That is matched to a separate
+ // lower complexity pattern with explicit register operand.
+ if (ShOpcVal == ARM_AM::no_shift) return false;
+
+ BaseReg = N.getOperand(0);
+ unsigned ShImmVal = 0;
+ if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+ ShImmVal = RHS->getZExtValue() & 31;
+ Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
+ return true;
+ }
+
+ return false;
+}
+
/// getAL - Returns a ARMCC::AL immediate node.
static inline SDValue getAL(SelectionDAG *CurDAG) {
return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
@@ -1003,6 +1000,6 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
/// createARMISelDag - This pass converts a legalized DAG into a
/// ARM-specific DAG, ready for instruction scheduling.
///
-FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) {
+FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM) {
return new ARMDAGToDAGISel(TM);
}
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 29d3da2..c24bb2e 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -266,7 +266,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::ROTL, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
- if (!Subtarget->hasV5TOps() || Subtarget->isThumb())
+ if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only())
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
// Only ARMv6 has BSWAP.
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index d70d2e2..d7371b0 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -742,32 +742,85 @@ class TIx2<dag outs, dag ins, string asm, list<dag> pattern>
class TJTI<dag outs, dag ins, string asm, list<dag> pattern>
: ThumbI<outs, ins, AddrModeNone, SizeSpecial, asm, "", pattern>;
-// ThumbPat - Same as Pat<>, but requires that the compiler be in Thumb mode.
-class ThumbPat<dag pattern, dag result> : Pat<pattern, result> {
+// TPat - Same as Pat<>, but requires that the compiler be in Thumb mode.
+class TPat<dag pattern, dag result> : Pat<pattern, result> {
list<Predicate> Predicates = [IsThumb];
}
-class ThumbV5Pat<dag pattern, dag result> : Pat<pattern, result> {
+class Tv5Pat<dag pattern, dag result> : Pat<pattern, result> {
list<Predicate> Predicates = [IsThumb, HasV5T];
}
-// T2I - Thumb2 instruction.
-
-class Thumb2I<dag outs, dag ins, AddrMode am, SizeFlagVal sz,
+// Thumb1 only
+class Thumb1I<dag outs, dag ins, AddrMode am, SizeFlagVal sz,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
let OutOperandList = outs;
let InOperandList = ins;
let AsmString = asm;
let Pattern = pattern;
+ list<Predicate> Predicates = [IsThumb1Only];
+}
+
+class T1I<dag outs, dag ins, string asm, list<dag> pattern>
+ : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>;
+
+// Two-address instructions
+class T1It<dag outs, dag ins, string asm, list<dag> pattern>
+ : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "$lhs = $dst", pattern>;
+
+class T1Pat<dag pattern, dag result> : Pat<pattern, result> {
+ list<Predicate> Predicates = [IsThumb1Only];
+}
+
+// Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable.
+class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+ string opc, string asm, string cstr, list<dag> pattern>
+ : InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
+ let OutOperandList = oops;
+ let InOperandList = !con(iops, (ops pred:$p));
+ let AsmString = !strconcat(opc, !strconcat("${p}", asm));
+ let Pattern = pattern;
+ list<Predicate> Predicates = [IsThumb, HasThumb2];
+}
+
+// Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as
+// an input operand since by default it's a zero register. It will
+// become an implicit def once it's "flipped".
+// FIXME: This uses unified syntax so {s} comes before {p}. We should make it
+// more consistent.
+class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+ string opc, string asm, string cstr, list<dag> pattern>
+ : InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
+ let OutOperandList = oops;
+ let InOperandList = !con(iops, (ops pred:$p, cc_out:$s));
+ let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
+ let Pattern = pattern;
+ list<Predicate> Predicates = [IsThumb, HasThumb2];
+}
+
+// Special cases
+class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+ string asm, string cstr, list<dag> pattern>
+ : InstARM<am, sz, IndexModeNone, ThumbFrm, cstr> {
+ let OutOperandList = oops;
+ let InOperandList = iops;
+ let AsmString = asm;
+ let Pattern = pattern;
list<Predicate> Predicates = [IsThumb, HasThumb2];
}
-class T2I<dag outs, dag ins, string asm, list<dag> pattern>
- : Thumb2I<outs, ins, AddrModeNone, Size4Bytes, asm, "", pattern>;
+class T2I<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb2I<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>;
+
+class T2sI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+ : Thumb2sI<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>;
+
+class T2XI<dag oops, dag iops, string asm, list<dag> pattern>
+ : Thumb2XI<oops, iops, AddrModeNone, Size4Bytes, asm, "", pattern>;
-// Thumb2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode.
-class Thumb2Pat<dag pattern, dag result> : Pat<pattern, result> {
+// T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode.
+class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
list<Predicate> Predicates = [IsThumb, HasThumb2];
}
diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
index e8da927..d95089d 100644
--- a/lib/Target/ARM/ARMInstrInfo.cpp
+++ b/lib/Target/ARM/ARMInstrInfo.cpp
@@ -39,11 +39,14 @@ const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
return MIB.addReg(0);
}
-ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
+ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &STI)
: TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
RI(*this, STI) {
}
+ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
+ : ARMBaseInstrInfo(STI) {
+}
/// Return true if the instruction is a register to register move and
/// leave the source and dest operands in the passed parameters.
@@ -65,10 +68,6 @@ bool ARMInstrInfo::isMoveInstr(const MachineInstr &MI,
DstReg = MI.getOperand(0).getReg();
return true;
case ARM::MOVr:
- case ARM::tMOVr:
- case ARM::tMOVhir2lor:
- case ARM::tMOVlor2hir:
- case ARM::tMOVhir2hir:
assert(MI.getDesc().getNumOperands() >= 2 &&
MI.getOperand(0).isReg() &&
MI.getOperand(1).isReg() &&
@@ -102,14 +101,6 @@ unsigned ARMInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
return MI->getOperand(0).getReg();
}
break;
- case ARM::tRestore:
- if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == 0) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
- }
- break;
}
return 0;
}
@@ -137,22 +128,15 @@ unsigned ARMInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
return MI->getOperand(0).getReg();
}
break;
- case ARM::tSpill:
- if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == 0) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
- }
- break;
}
+
return 0;
}
-void ARMInstrInfo::reMaterialize(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg,
- const MachineInstr *Orig) const {
+void ARMBaseInstrInfo::reMaterialize(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg,
+ const MachineInstr *Orig) const {
DebugLoc dl = Orig->getDebugLoc();
if (Orig->getOpcode() == ARM::MOVi2pieces) {
RI.emitLoadConstPool(MBB, I, DestReg, Orig->getOperand(1).getImm(),
@@ -198,9 +182,9 @@ static unsigned getUnindexedOpcode(unsigned Opc) {
}
MachineInstr *
-ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
- MachineBasicBlock::iterator &MBBI,
- LiveVariables *LV) const {
+ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
+ MachineBasicBlock::iterator &MBBI,
+ LiveVariables *LV) const {
if (!EnableARM3Addr)
return NULL;
@@ -261,7 +245,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
.addImm(Pred).addReg(0).addReg(0);
- } else
+ } else
UpdateMI = BuildMI(MF, MI->getDebugLoc(),
get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
.addReg(BaseReg).addReg(OffReg)
@@ -312,7 +296,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
NewMIs.push_back(UpdateMI);
NewMIs.push_back(MemMI);
}
-
+
// Transfer LiveVariables states, kill / dead info.
if (LV) {
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
@@ -320,7 +304,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
if (MO.isReg() && MO.getReg() &&
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
unsigned Reg = MO.getReg();
-
+
LiveVariables::VarInfo &VI = LV->getVarInfo(Reg);
if (MO.isDef()) {
MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI;
@@ -349,18 +333,19 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
}
// Branch analysis.
-bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
- MachineBasicBlock *&FBB,
- SmallVectorImpl<MachineOperand> &Cond,
- bool AllowModify) const {
+bool
+ ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
// If the block has no terminators, it just falls into the block after it.
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
return false;
-
+
// Get the last instruction in the block.
MachineInstr *LastInst = I;
-
+
// If there is only one terminator instruction, process it.
unsigned LastOpc = LastInst->getOpcode();
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
@@ -377,14 +362,14 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
}
return true; // Can't handle indirect branch.
}
-
+
// Get the instruction before it if it is a terminator.
MachineInstr *SecondLastInst = I;
-
+
// If there are three terminators, we don't know what sort of block this is.
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.
unsigned SecondLastOpc = SecondLastInst->getOpcode();
if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) ||
@@ -395,8 +380,8 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
FBB = LastInst->getOperand(0).getMBB();
return false;
}
-
- // If the block ends with two unconditional branches, handle it. The second
+
+ // 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)) {
@@ -417,14 +402,14 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
if (AllowModify)
I->eraseFromParent();
return true;
- }
+ }
// Otherwise, can't handle this.
return true;
}
-unsigned ARMInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
+unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
MachineFunction &MF = *MBB.getParent();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
int BOpc = AFI->isThumbFunction() ? ARM::tB : ARM::B;
@@ -435,26 +420,26 @@ unsigned ARMInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
--I;
if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc)
return 0;
-
+
// Remove the branch.
I->eraseFromParent();
-
+
I = MBB.end();
-
+
if (I == MBB.begin()) return 1;
--I;
if (I->getOpcode() != BccOpc)
return 1;
-
+
// Remove the branch.
I->eraseFromParent();
return 2;
}
unsigned
-ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond) const {
+ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const {
// FIXME this should probably have a DebugLoc argument
DebugLoc dl = DebugLoc::getUnknownLoc();
MachineFunction &MF = *MBB.getParent();
@@ -466,7 +451,7 @@ ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
assert((Cond.size() == 2 || Cond.size() == 0) &&
"ARM branch conditions have two components!");
-
+
if (FBB == 0) {
if (Cond.empty()) // Unconditional branch?
BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB);
@@ -475,7 +460,7 @@ ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
return 1;
}
-
+
// Two-way conditional branch.
BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
@@ -488,43 +473,18 @@ bool ARMInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
DebugLoc DL = DebugLoc::getUnknownLoc();
if (I != MBB.end()) DL = I->getDebugLoc();
- if (!AFI->isThumbFunction()) {
- if (DestRC == ARM::GPRRegisterClass) {
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), DestReg)
- .addReg(SrcReg)));
- return true;
- }
- } else {
- if (DestRC == ARM::GPRRegisterClass) {
- if (SrcRC == ARM::GPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg);
- return true;
- } else if (SrcRC == ARM::tGPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
- return true;
- }
- } else if (DestRC == ARM::tGPRRegisterClass) {
- if (SrcRC == ARM::GPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
- return true;
- } else if (SrcRC == ARM::tGPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
- return true;
- }
- }
- }
if (DestRC != SrcRC) {
// Not yet supported!
return false;
}
-
- if (DestRC == ARM::SPRRegisterClass)
+ if (DestRC == ARM::GPRRegisterClass)
+ AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), DestReg)
+ .addReg(SrcReg)));
+ else if (DestRC == ARM::SPRRegisterClass)
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYS), DestReg)
.addReg(SrcReg));
else if (DestRC == ARM::DPRRegisterClass)
@@ -534,7 +494,7 @@ bool ARMInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
BuildMI(MBB, I, DL, get(ARM::VMOVQ), DestReg).addReg(SrcReg);
else
return false;
-
+
return true;
}
@@ -546,19 +506,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
if (I != MBB.end()) DL = I->getDebugLoc();
if (RC == ARM::GPRRegisterClass) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- assert (!AFI->isThumbFunction());
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR))
.addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FI).addReg(0).addImm(0));
- } else if (RC == ARM::tGPRRegisterClass) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- assert (AFI->isThumbFunction());
- BuildMI(MBB, I, DL, get(ARM::tSpill))
- .addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
} else if (RC == ARM::DPRRegisterClass) {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FSTD))
.addReg(SrcReg, getKillRegState(isKill))
@@ -579,16 +529,6 @@ void ARMInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
DebugLoc DL = DebugLoc::getUnknownLoc();
unsigned Opc = 0;
if (RC == ARM::GPRRegisterClass) {
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- if (AFI->isThumbFunction()) {
- Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
- MachineInstrBuilder MIB =
- BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- NewMIs.push_back(MIB);
- return;
- }
Opc = ARM::STR;
} else if (RC == ARM::DPRRegisterClass) {
Opc = ARM::FSTD;
@@ -597,7 +537,7 @@ void ARMInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
Opc = ARM::FSTS;
}
- MachineInstrBuilder MIB =
+ MachineInstrBuilder MIB =
BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
MIB.addOperand(Addr[i]);
@@ -614,17 +554,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
if (I != MBB.end()) DL = I->getDebugLoc();
if (RC == ARM::GPRRegisterClass) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- assert (!AFI->isThumbFunction());
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg)
.addFrameIndex(FI).addReg(0).addImm(0));
- } else if (RC == ARM::tGPRRegisterClass) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- assert (AFI->isThumbFunction());
- BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
- .addFrameIndex(FI).addImm(0);
} else if (RC == ARM::DPRRegisterClass) {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FLDD), DestReg)
.addFrameIndex(FI).addImm(0));
@@ -643,15 +574,6 @@ loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
DebugLoc DL = DebugLoc::getUnknownLoc();
unsigned Opc = 0;
if (RC == ARM::GPRRegisterClass) {
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- if (AFI->isThumbFunction()) {
- Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
- MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- NewMIs.push_back(MIB);
- return;
- }
Opc = ARM::LDR;
} else if (RC == ARM::DPRRegisterClass) {
Opc = ARM::FLDD;
@@ -668,59 +590,6 @@ loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
return;
}
-bool ARMInstrInfo::
-spillCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- if (!AFI->isThumbFunction() || CSI.empty())
- return false;
-
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
-
- MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
- for (unsigned i = CSI.size(); i != 0; --i) {
- unsigned Reg = CSI[i-1].getReg();
- // Add the callee-saved register as live-in. It's killed at the spill.
- MBB.addLiveIn(Reg);
- MIB.addReg(Reg, RegState::Kill);
- }
- return true;
-}
-
-bool ARMInstrInfo::
-restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- if (!AFI->isThumbFunction() || CSI.empty())
- return false;
-
- bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
- MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
- for (unsigned i = CSI.size(); i != 0; --i) {
- unsigned Reg = CSI[i-1].getReg();
- if (Reg == ARM::LR) {
- // Special epilogue for vararg functions. See emitEpilogue
- if (isVarArg)
- continue;
- Reg = ARM::PC;
- PopMI->setDesc(get(ARM::tPOP_RET));
- MI = MBB.erase(MI);
- }
- PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
- }
-
- // It's illegal to emit pop instruction without operands.
- if (PopMI->getNumOperands() > 0)
- MBB.insert(MI, PopMI);
-
- return true;
-}
-
MachineInstr *ARMInstrInfo::
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops, int FI) const {
@@ -752,31 +621,6 @@ foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
}
break;
}
- case ARM::tMOVr:
- case ARM::tMOVlor2hir:
- case ARM::tMOVhir2lor:
- case ARM::tMOVhir2hir: {
- if (OpNum == 0) { // move -> store
- unsigned SrcReg = MI->getOperand(1).getReg();
- bool isKill = MI->getOperand(1).isKill();
- if (RI.isPhysicalRegister(SrcReg) && !RI.isLowRegister(SrcReg))
- // tSpill cannot take a high register operand.
- break;
- NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
- .addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- } else { // move -> load
- unsigned DstReg = MI->getOperand(0).getReg();
- if (RI.isPhysicalRegister(DstReg) && !RI.isLowRegister(DstReg))
- // tRestore cannot target a high register operand.
- break;
- bool isDead = MI->getOperand(0).isDead();
- NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
- .addReg(DstReg, RegState::Define | getDeadRegState(isDead))
- .addFrameIndex(FI).addImm(0);
- }
- break;
- }
case ARM::FCPYS: {
unsigned Pred = MI->getOperand(2).getImm();
unsigned PredReg = MI->getOperand(3).getReg();
@@ -816,7 +660,7 @@ foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
return NewMI;
}
-bool ARMInstrInfo::
+bool ARMBaseInstrInfo::
canFoldMemoryOperand(const MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops) const {
if (Ops.size() != 1) return false;
@@ -857,9 +701,10 @@ canFoldMemoryOperand(const MachineInstr *MI,
return false;
}
-bool ARMInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
+bool
+ ARMBaseInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
if (MBB.empty()) return false;
-
+
switch (MBB.back().getOpcode()) {
case ARM::BX_RET: // Return.
case ARM::LDM_RET:
@@ -877,19 +722,19 @@ bool ARMInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
}
}
-bool ARMInstrInfo::
+bool ARMBaseInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
Cond[0].setImm(ARMCC::getOppositeCondition(CC));
return false;
}
-bool ARMInstrInfo::isPredicated(const MachineInstr *MI) const {
+bool ARMBaseInstrInfo::isPredicated(const MachineInstr *MI) const {
int PIdx = MI->findFirstPredOperandIdx();
return PIdx != -1 && MI->getOperand(PIdx).getImm() != ARMCC::AL;
}
-bool ARMInstrInfo::
+bool ARMBaseInstrInfo::
PredicateInstruction(MachineInstr *MI,
const SmallVectorImpl<MachineOperand> &Pred) const {
unsigned Opc = MI->getOpcode();
@@ -910,7 +755,7 @@ PredicateInstruction(MachineInstr *MI,
return false;
}
-bool ARMInstrInfo::
+bool ARMBaseInstrInfo::
SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
const SmallVectorImpl<MachineOperand> &Pred2) const {
if (Pred1.size() > 2 || Pred2.size() > 2)
@@ -937,7 +782,7 @@ SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
}
}
-bool ARMInstrInfo::DefinesPredicate(MachineInstr *MI,
+bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
std::vector<MachineOperand> &Pred) const {
const TargetInstrDesc &TID = MI->getDesc();
if (!TID.getImplicitDefs() && !TID.hasOptionalDef())
@@ -966,7 +811,7 @@ static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
/// GetInstSize - Return the size of the specified MachineInstr.
///
-unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
+unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
const MachineBasicBlock &MBB = *MI->getParent();
const MachineFunction *MF = MBB.getParent();
const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
@@ -974,7 +819,7 @@ unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
// Basic size info comes from the TSFlags field.
const TargetInstrDesc &TID = MI->getDesc();
unsigned TSFlags = TID.TSFlags;
-
+
switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
default: {
// If this machine instr is an inline asm, measure it.
@@ -1024,7 +869,7 @@ unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
// FIXME: If we know the size of the function is less than (1 << 16) *2
// bytes, we can use 16-bit entries instead. Then there won't be an
// alignment issue.
- return getNumJTEntries(JT, JTI) * 4 +
+ return getNumJTEntries(JT, JTI) * 4 +
(MI->getOpcode()==ARM::tBR_JTr ? 2 : 4);
}
default:
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index 9658f3b..131960b 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -51,14 +51,14 @@ namespace ARMII {
Size8Bytes = 2,
Size4Bytes = 3,
Size2Bytes = 4,
-
+
// IndexMode - Unindex, pre-indexed, or post-indexed. Only valid for load
- // and store ops
+ // and store ops
IndexModeShift = 7,
IndexModeMask = 3 << IndexModeShift,
IndexModePre = 1,
IndexModePost = 2,
-
+
//===------------------------------------------------------------------===//
// Misc flags.
@@ -146,10 +146,12 @@ namespace ARMII {
};
}
-class ARMInstrInfo : public TargetInstrInfoImpl {
+class ARMBaseInstrInfo : public TargetInstrInfoImpl {
const ARMRegisterInfo RI;
+protected:
+ // Can be only subclassed.
+ explicit ARMBaseInstrInfo(const ARMSubtarget &STI);
public:
- explicit ARMInstrInfo(const ARMSubtarget &STI);
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
@@ -157,17 +159,6 @@ public:
///
virtual const ARMRegisterInfo &getRegisterInfo() const { return RI; }
- /// Return true if the instruction is a register to register move and return
- /// the source and dest operands and their sub-register indices by reference.
- virtual bool isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg,
- unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
-
- virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
- virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
-
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
unsigned DestReg, const MachineInstr *Orig) const;
@@ -184,6 +175,54 @@ public:
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const;
+
+ virtual bool canFoldMemoryOperand(const MachineInstr *MI,
+ const SmallVectorImpl<unsigned> &Ops) const;
+
+ virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
+ virtual
+ bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
+
+ // Predication support.
+ virtual bool isPredicated(const MachineInstr *MI) const;
+
+ ARMCC::CondCodes getPredicate(const MachineInstr *MI) const {
+ int PIdx = MI->findFirstPredOperandIdx();
+ return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm()
+ : ARMCC::AL;
+ }
+
+ virtual
+ bool PredicateInstruction(MachineInstr *MI,
+ const SmallVectorImpl<MachineOperand> &Pred) const;
+
+ virtual
+ bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
+ const SmallVectorImpl<MachineOperand> &Pred2) const;
+
+ virtual bool DefinesPredicate(MachineInstr *MI,
+ std::vector<MachineOperand> &Pred) const;
+
+ /// GetInstSize - Returns the size of the specified MachineInstr.
+ ///
+ virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const;
+};
+
+class ARMInstrInfo : public ARMBaseInstrInfo {
+public:
+ explicit ARMInstrInfo(const ARMSubtarget &STI);
+
+ /// Return true if the instruction is a register to register move and return
+ /// the source and dest operands and their sub-register indices by reference.
+ virtual bool isMoveInstr(const MachineInstr &MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
+
+ virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+ virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+
virtual bool copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
@@ -208,13 +247,7 @@ public:
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const;
- virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const;
- virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI) const;
-
+
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
@@ -226,37 +259,6 @@ public:
MachineInstr* LoadMI) const {
return 0;
}
-
- virtual bool canFoldMemoryOperand(const MachineInstr *MI,
- const SmallVectorImpl<unsigned> &Ops) const;
-
- virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
- virtual
- bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
-
- // Predication support.
- virtual bool isPredicated(const MachineInstr *MI) const;
-
- ARMCC::CondCodes getPredicate(const MachineInstr *MI) const {
- int PIdx = MI->findFirstPredOperandIdx();
- return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm()
- : ARMCC::AL;
- }
-
- virtual
- bool PredicateInstruction(MachineInstr *MI,
- const SmallVectorImpl<MachineOperand> &Pred) const;
-
- virtual
- bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
- const SmallVectorImpl<MachineOperand> &Pred2) const;
-
- virtual bool DefinesPredicate(MachineInstr *MI,
- std::vector<MachineOperand> &Pred) const;
-
- /// GetInstSize - Returns the size of the specified MachineInstr.
- ///
- virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const;
};
}
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 7003a65..cb7b7b9 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -103,6 +103,8 @@ def HasThumb2 : Predicate<"Subtarget->hasThumb2()">;
def IsARM : Predicate<"!Subtarget->isThumb()">;
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">;
+def CarryDefIsUnused : Predicate<"!N.getNode()->hasAnyUseOfValue(1)">;
+def CarryDefIsUsed : Predicate<"N.getNode()->hasAnyUseOfValue(1)">;
//===----------------------------------------------------------------------===//
// ARM Flag Definitions.
@@ -353,28 +355,34 @@ include "ARMInstrFormats.td"
/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a
/// binop that produces a value.
-multiclass AsI1_bin_irs<bits<4> opcod, string opc, PatFrag opnode> {
+multiclass AsI1_bin_irs<bits<4> opcod, string opc, PatFrag opnode,
+ bit Commutable = 0> {
def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
opc, " $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
def rr : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm,
opc, " $dst, $a, $b",
- [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]> {
+ let isCommutable = Commutable;
+ }
def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, " $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
}
-/// ASI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
+/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
/// instruction modifies the CSPR register.
let Defs = [CPSR] in {
-multiclass ASI1_bin_s_irs<bits<4> opcod, string opc, PatFrag opnode> {
+multiclass AI1_bin_s_irs<bits<4> opcod, string opc, PatFrag opnode,
+ bit Commutable = 0> {
def ri : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
opc, "s $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
def rr : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm,
opc, "s $dst, $a, $b",
- [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]> {
+ let isCommutable = Commutable;
+ }
def rs : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, "s $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
@@ -385,13 +393,16 @@ multiclass ASI1_bin_s_irs<bits<4> opcod, string opc, PatFrag opnode> {
/// patterns. Similar to AsI1_bin_irs except the instruction does not produce
/// a explicit result, only implicitly set CPSR.
let Defs = [CPSR] in {
-multiclass AI1_cmp_irs<bits<4> opcod, string opc, PatFrag opnode> {
+multiclass AI1_cmp_irs<bits<4> opcod, string opc, PatFrag opnode,
+ bit Commutable = 0> {
def ri : AI1<opcod, (outs), (ins GPR:$a, so_imm:$b), DPFrm,
opc, " $a, $b",
[(opnode GPR:$a, so_imm:$b)]>;
def rr : AI1<opcod, (outs), (ins GPR:$a, GPR:$b), DPFrm,
opc, " $a, $b",
- [(opnode GPR:$a, GPR:$b)]>;
+ [(opnode GPR:$a, GPR:$b)]> {
+ let isCommutable = Commutable;
+ }
def rs : AI1<opcod, (outs), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, " $a, $b",
[(opnode GPR:$a, so_reg:$b)]>;
@@ -430,19 +441,43 @@ multiclass AI_bin_rrot<bits<8> opcod, string opc, PatFrag opnode> {
Requires<[IsARM, HasV6]>;
}
-/// AsXI1_bin_c_irs - Same as AsI1_bin_irs but without the predicate operand and
-/// setting carry bit. But it can optionally set CPSR.
+/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
let Uses = [CPSR] in {
-multiclass AsXI1_bin_c_irs<bits<4> opcod, string opc, PatFrag opnode> {
- def ri : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b, cc_out:$s),
- DPFrm, !strconcat(opc, "${s} $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
- def rr : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b, cc_out:$s),
- DPFrm, !strconcat(opc, "${s} $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
- def rs : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b, cc_out:$s),
- DPSoRegFrm, !strconcat(opc, "${s} $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
+multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
+ bit Commutable = 0> {
+ def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+ def rr : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
+ DPFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]> {
+ let isCommutable = Commutable;
+ }
+ def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+ // Carry setting variants
+ def Sri : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, !strconcat(opc, "s $dst, $a, $b"),
+ [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ def Srr : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
+ DPFrm, !strconcat(opc, "s $dst, $a, $b"),
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ def Srs : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, !strconcat(opc, "s $dst, $a, $b"),
+ [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
}
}
@@ -535,7 +570,8 @@ def LEApcrel : AXI1<0x0, (outs GPR:$dst), (ins i32imm:$label, pred:$p), Pseudo,
"add$p $dst, pc, #PCRELV${:uid}")),
[]>;
-def LEApcrelJT : AXI1<0x0, (outs GPR:$dst), (ins i32imm:$label, i32imm:$id, pred:$p),
+def LEApcrelJT : AXI1<0x0, (outs GPR:$dst),
+ (ins i32imm:$label, i32imm:$id, pred:$p),
Pseudo,
!strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
"${:private}PCRELL${:uid}+8))\n"),
@@ -899,21 +935,20 @@ defm UXTAH : AI_bin_rrot<0b01101111, "uxtah",
//
defm ADD : AsI1_bin_irs<0b0100, "add",
- BinOpFrag<(add node:$LHS, node:$RHS)>>;
+ BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
defm SUB : AsI1_bin_irs<0b0010, "sub",
BinOpFrag<(sub node:$LHS, node:$RHS)>>;
// ADD and SUB with 's' bit set.
-defm ADDS : ASI1_bin_s_irs<0b0100, "add",
- BinOpFrag<(addc node:$LHS, node:$RHS)>>;
-defm SUBS : ASI1_bin_s_irs<0b0010, "sub",
- BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+defm ADDS : AI1_bin_s_irs<0b0100, "add",
+ BinOpFrag<(addc node:$LHS, node:$RHS)>>;
+defm SUBS : AI1_bin_s_irs<0b0010, "sub",
+ BinOpFrag<(subc node:$LHS, node:$RHS)>>;
-// FIXME: Do not allow ADC / SBC to be predicated for now.
-defm ADC : AsXI1_bin_c_irs<0b0101, "adc",
- BinOpFrag<(adde node:$LHS, node:$RHS)>>;
-defm SBC : AsXI1_bin_c_irs<0b0110, "sbc",
- BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm ADC : AI1_adde_sube_irs<0b0101, "adc",
+ BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>;
+defm SBC : AI1_adde_sube_irs<0b0110, "sbc",
+ BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// These don't define reg/reg forms, because they are handled above.
def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
@@ -934,14 +969,27 @@ def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
[(set GPR:$dst, (subc so_reg:$b, GPR:$a))]>;
}
-// FIXME: Do not allow RSC to be predicated for now. But they can set CPSR.
let Uses = [CPSR] in {
-def RSCri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b, cc_out:$s),
- DPFrm, "rsc${s} $dst, $a, $b",
- [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>;
-def RSCrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b, cc_out:$s),
- DPSoRegFrm, "rsc${s} $dst, $a, $b",
- [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>;
+def RSCri : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, "rsc", " $dst, $a, $b",
+ [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, "rsc", " $dst, $a, $b",
+ [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+}
+
+// FIXME: Allow these to be predicated.
+let Defs = [CPSR], Uses = [CPSR] in {
+def RSCSri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, "rscs $dst, $a, $b",
+ [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, "rscs $dst, $a, $b",
+ [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
@@ -965,11 +1013,11 @@ def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
//
defm AND : AsI1_bin_irs<0b0000, "and",
- BinOpFrag<(and node:$LHS, node:$RHS)>>;
+ BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
defm ORR : AsI1_bin_irs<0b1100, "orr",
- BinOpFrag<(or node:$LHS, node:$RHS)>>;
+ BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
defm EOR : AsI1_bin_irs<0b0001, "eor",
- BinOpFrag<(xor node:$LHS, node:$RHS)>>;
+ BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
defm BIC : AsI1_bin_irs<0b1110, "bic",
BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
@@ -991,6 +1039,7 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm),
// Multiply Instructions.
//
+let isCommutable = 1 in
def MUL : AsMul1I<0b0000000, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
"mul", " $dst, $a, $b",
[(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
@@ -1001,6 +1050,7 @@ def MLA : AsMul1I<0b0000001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
// Extra precision multiplies with low / high results
let neverHasSideEffects = 1 in {
+let isCommutable = 1 in {
def SMULL : AsMul1I<0b0000110, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b),
"smull", " $ldst, $hdst, $a, $b", []>;
@@ -1008,6 +1058,7 @@ def SMULL : AsMul1I<0b0000110, (outs GPR:$ldst, GPR:$hdst),
def UMULL : AsMul1I<0b0000100, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b),
"umull", " $ldst, $hdst, $a, $b", []>;
+}
// Multiply + accumulate
def SMLAL : AsMul1I<0b0000111, (outs GPR:$ldst, GPR:$hdst),
@@ -1258,9 +1309,9 @@ defm CMN : AI1_cmp_irs<0b1011, "cmn",
// Note that TST/TEQ don't set all the same flags that CMP does!
defm TST : AI1_cmp_irs<0b1000, "tst",
- BinOpFrag<(ARMcmpNZ (and node:$LHS, node:$RHS), 0)>>;
+ BinOpFrag<(ARMcmpNZ (and node:$LHS, node:$RHS), 0)>, 1>;
defm TEQ : AI1_cmp_irs<0b1001, "teq",
- BinOpFrag<(ARMcmpNZ (xor node:$LHS, node:$RHS), 0)>>;
+ BinOpFrag<(ARMcmpNZ (xor node:$LHS, node:$RHS), 0)>, 1>;
defm CMPnz : AI1_cmp_irs<0b1010, "cmp",
BinOpFrag<(ARMcmpNZ node:$LHS, node:$RHS)>>;
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 1def093..7927ca5 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -128,10 +128,28 @@ PseudoInst<(outs), (ins i32imm:$amt),
}
let isNotDuplicable = 1 in
-def tPICADD : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp),
+def tPICADD : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp),
"$cp:\n\tadd $dst, pc",
[(set tGPR:$dst, (ARMpic_add tGPR:$lhs, imm:$cp))]>;
+// PC relative add.
+def tADDrPCi : T1I<(outs tGPR:$dst), (ins i32imm:$rhs),
+ "add $dst, pc, $rhs * 4", []>;
+
+// ADD rd, sp, #imm8
+// FIXME: hard code sp?
+def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
+ "add $dst, $sp, $rhs * 4 @ addrspi", []>;
+
+// ADD sp, sp, #imm7
+// FIXME: hard code sp?
+def tADDspi : T1It<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ "add $dst, $rhs * 4", []>;
+
+// FIXME: Make use of the following?
+// ADD rm, sp, rm
+// ADD sp, rm
+
//===----------------------------------------------------------------------===//
// Control Flow Instructions.
//
@@ -276,113 +294,135 @@ def tPUSH : TI<(outs), (ins reglist:$src1, variable_ops),
// Arithmetic Instructions.
//
-// Add with carry
-let isCommutable = 1 in
-def tADC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "adc $dst, $rhs",
- [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
+// Add with carry register
+let isCommutable = 1, Defs = [CPSR], Uses = [CPSR] in
+def tADCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "adc $dst, $rhs",
+ [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
-def tADDS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "add $dst, $lhs, $rhs",
- [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
-
-
-def tADDi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// Add immediate
+let Defs = [CPSR] in {
+def tADDi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"add $dst, $lhs, $rhs",
[(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>;
+def tADDSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "add $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7:$rhs))]>;
+}
-def tADDi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+let Defs = [CPSR] in {
+def tADDi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"add $dst, $rhs",
[(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>;
+def tADDSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "add $dst, $rhs",
+ [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255:$rhs))]>;
+}
-def tADDrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// Add register
+let isCommutable = 1, Defs = [CPSR] in {
+def tADDrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"add $dst, $lhs, $rhs",
[(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>;
+def tADDSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "add $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (addc tGPR:$lhs, tGPR:$rhs))]>;
+}
let neverHasSideEffects = 1 in
-def tADDhirr : TIt<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+def tADDhirr : T1It<(outs tGPR:$dst), (ins GPR:$lhs, GPR:$rhs),
"add $dst, $rhs @ addhirr", []>;
-def tADDrPCi : TI<(outs tGPR:$dst), (ins i32imm:$rhs),
- "add $dst, pc, $rhs * 4", []>;
-
-def tADDrSPi : TI<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
- "add $dst, $sp, $rhs * 4 @ addrspi", []>;
-
-def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
- "add $dst, $rhs * 4", []>;
-
-let isCommutable = 1 in
-def tAND : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// And register
+let isCommutable = 1, Defs = [CPSR] in
+def tAND : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"and $dst, $rhs",
[(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
-def tASRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// ASR immediate
+let Defs = [CPSR] in
+def tASRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"asr $dst, $lhs, $rhs",
[(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>;
-def tASRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// ASR register
+let Defs = [CPSR] in
+def tASRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"asr $dst, $rhs",
[(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>;
-def tBIC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// BIC register
+let Defs = [CPSR] in
+def tBIC : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"bic $dst, $rhs",
[(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>;
-
-def tCMN : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+// CMN register
+let Defs = [CPSR] in {
+def tCMN : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
"cmn $lhs, $rhs",
[(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
-
-def tCMPi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
-
-def tCMPr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "cmp $lhs, $rhs",
- [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
-
-def tTST : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
- "tst $lhs, $rhs",
- [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
-
-def tCMNNZ : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+def tCMNNZ : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
"cmn $lhs, $rhs",
[(ARMcmpNZ tGPR:$lhs, (ineg tGPR:$rhs))]>;
+}
-def tCMPNZi8 : TI<(outs), (ins tGPR:$lhs, i32imm:$rhs),
+// CMP immediate
+let Defs = [CPSR] in {
+def tCMPi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
+ "cmp $lhs, $rhs",
+ [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>;
+def tCMPNZi8 : T1I<(outs), (ins tGPR:$lhs, i32imm:$rhs),
"cmp $lhs, $rhs",
[(ARMcmpNZ tGPR:$lhs, imm0_255:$rhs)]>;
-def tCMPNZr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+}
+
+// CMP register
+let Defs = [CPSR] in {
+def tCMPr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "cmp $lhs, $rhs",
+ [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>;
+def tCMPNZr : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
"cmp $lhs, $rhs",
[(ARMcmpNZ tGPR:$lhs, tGPR:$rhs)]>;
+}
// TODO: A7-37: CMP(3) - cmp hi regs
-let isCommutable = 1 in
-def tEOR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// XOR register
+let isCommutable = 1, Defs = [CPSR] in
+def tEOR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"eor $dst, $rhs",
[(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
-def tLSLri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// LSL immediate
+let Defs = [CPSR] in
+def tLSLri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"lsl $dst, $lhs, $rhs",
[(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>;
-def tLSLrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// LSL register
+let Defs = [CPSR] in
+def tLSLrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"lsl $dst, $rhs",
[(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>;
-def tLSRri : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// LSR immediate
+let Defs = [CPSR] in
+def tLSRri : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"lsr $dst, $lhs, $rhs",
[(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>;
-def tLSRrr : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// LSR register
+let Defs = [CPSR] in
+def tLSRrr : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"lsr $dst, $rhs",
[(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>;
-// FIXME: This is not rematerializable because mov changes the condition code.
-def tMOVi8 : TI<(outs tGPR:$dst), (ins i32imm:$src),
+// move register
+let Defs = [CPSR] in
+def tMOVi8 : T1I<(outs tGPR:$dst), (ins i32imm:$src),
"mov $dst, $src",
[(set tGPR:$dst, imm0_255:$src)]>;
@@ -392,41 +432,47 @@ def tMOVi8 : TI<(outs tGPR:$dst), (ins i32imm:$src),
// Note: MOV(2) of two low regs updates the flags, so we emit this as 'cpy',
// which is MOV(3). This also supports high registers.
let neverHasSideEffects = 1 in {
-def tMOVr : TI<(outs tGPR:$dst), (ins tGPR:$src),
+def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"cpy $dst, $src", []>;
-def tMOVhir2lor : TI<(outs tGPR:$dst), (ins GPR:$src),
+def tMOVhir2lor : T1I<(outs tGPR:$dst), (ins GPR:$src),
"cpy $dst, $src\t@ hir2lor", []>;
-def tMOVlor2hir : TI<(outs GPR:$dst), (ins tGPR:$src),
+def tMOVlor2hir : T1I<(outs GPR:$dst), (ins tGPR:$src),
"cpy $dst, $src\t@ lor2hir", []>;
-def tMOVhir2hir : TI<(outs GPR:$dst), (ins GPR:$src),
+def tMOVhir2hir : T1I<(outs GPR:$dst), (ins GPR:$src),
"cpy $dst, $src\t@ hir2hir", []>;
} // neverHasSideEffects
-let isCommutable = 1 in
-def tMUL : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// multiply register
+let isCommutable = 1, Defs = [CPSR] in
+def tMUL : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"mul $dst, $rhs",
[(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
-def tMVN : TI<(outs tGPR:$dst), (ins tGPR:$src),
+// move inverse register
+let Defs = [CPSR] in
+def tMVN : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"mvn $dst, $src",
[(set tGPR:$dst, (not tGPR:$src))]>;
-def tNEG : TI<(outs tGPR:$dst), (ins tGPR:$src),
+// negate register
+let Defs = [CPSR] in
+def tNEG : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"neg $dst, $src",
[(set tGPR:$dst, (ineg tGPR:$src))]>;
-let isCommutable = 1 in
-def tORR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// bitwise or register
+let isCommutable = 1, Defs = [CPSR] in
+def tORR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"orr $dst, $rhs",
[(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
-
-def tREV : TI<(outs tGPR:$dst), (ins tGPR:$src),
+// swaps
+def tREV : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"rev $dst, $src",
[(set tGPR:$dst, (bswap tGPR:$src))]>,
Requires<[IsThumb, HasV6]>;
-def tREV16 : TI<(outs tGPR:$dst), (ins tGPR:$src),
+def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"rev16 $dst, $src",
[(set tGPR:$dst,
(or (and (srl tGPR:$src, (i32 8)), 0xFF),
@@ -435,7 +481,7 @@ def tREV16 : TI<(outs tGPR:$dst), (ins tGPR:$src),
(and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
Requires<[IsThumb, HasV6]>;
-def tREVSH : TI<(outs tGPR:$dst), (ins tGPR:$src),
+def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"revsh $dst, $src",
[(set tGPR:$dst,
(sext_inreg
@@ -443,53 +489,78 @@ def tREVSH : TI<(outs tGPR:$dst), (ins tGPR:$src),
(shl tGPR:$src, (i32 8))), i16))]>,
Requires<[IsThumb, HasV6]>;
-def tROR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// rotate right register
+let Defs = [CPSR] in
+def tROR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"ror $dst, $rhs",
[(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>;
-
-// Subtract with carry
-def tSBC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// Subtract with carry register
+let Defs = [CPSR], Uses = [CPSR] in
+def tSBCS : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"sbc $dst, $rhs",
[(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>;
-def tSUBS : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
- "sub $dst, $lhs, $rhs",
- [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
-
-
-// TODO: A7-96: STMIA - store multiple.
-
-def tSUBi3 : TI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// Subtract immediate
+let Defs = [CPSR] in {
+def tSUBi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"sub $dst, $lhs, $rhs",
[(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>;
+def tSUBSi3 : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "sub $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (addc tGPR:$lhs, imm0_7_neg:$rhs))]>;
+}
-def tSUBi8 : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+let Defs = [CPSR] in {
+def tSUBi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"sub $dst, $rhs",
[(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>;
+def tSUBSi8 : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+ "sub $dst, $rhs",
+ [(set tGPR:$dst, (addc tGPR:$lhs, imm8_255_neg:$rhs))]>;
+}
-def tSUBrr : TI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+// subtract register
+let Defs = [CPSR] in {
+def tSUBrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"sub $dst, $lhs, $rhs",
[(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>;
+def tSUBSrr : T1I<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
+ "sub $dst, $lhs, $rhs",
+ [(set tGPR:$dst, (subc tGPR:$lhs, tGPR:$rhs))]>;
+}
-def tSUBspi : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
+// TODO: A7-96: STMIA - store multiple.
+
+def tSUBspi : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
"sub $dst, $rhs * 4", []>;
-def tSXTB : TI<(outs tGPR:$dst), (ins tGPR:$src),
+// sign-extend byte
+def tSXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"sxtb $dst, $src",
[(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
Requires<[IsThumb, HasV6]>;
-def tSXTH : TI<(outs tGPR:$dst), (ins tGPR:$src),
+
+// sign-extend short
+def tSXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"sxth $dst, $src",
[(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
Requires<[IsThumb, HasV6]>;
+// test
+let isCommutable = 1, Defs = [CPSR] in
+def tTST : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
+ "tst $lhs, $rhs",
+ [(ARMcmpNZ (and tGPR:$lhs, tGPR:$rhs), 0)]>;
-def tUXTB : TI<(outs tGPR:$dst), (ins tGPR:$src),
+// zero-extend byte
+def tUXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"uxtb $dst, $src",
[(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
Requires<[IsThumb, HasV6]>;
-def tUXTH : TI<(outs tGPR:$dst), (ins tGPR:$src),
+
+// zero-extend short
+def tUXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"uxth $dst, $src",
[(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
Requires<[IsThumb, HasV6]>;
@@ -536,35 +607,35 @@ let isCall = 1,
//
// ConstantPool, GlobalAddress
-def : ThumbPat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
-def : ThumbPat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>;
+def : TPat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
+def : TPat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>;
// JumpTable
-def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
- (tLEApcrelJT tjumptable:$dst, imm:$id)>;
+def : TPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
+ (tLEApcrelJT tjumptable:$dst, imm:$id)>;
// Direct calls
-def : ThumbPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
-def : ThumbV5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
+def : TPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>;
+def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;
// Indirect calls to ARM routines
-def : ThumbV5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
+def : Tv5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>;
// zextload i1 -> zextload i8
-def : ThumbPat<(zextloadi1 t_addrmode_s1:$addr),
- (tLDRB t_addrmode_s1:$addr)>;
+def : TPat<(zextloadi1 t_addrmode_s1:$addr),
+ (tLDRB t_addrmode_s1:$addr)>;
// extload -> zextload
-def : ThumbPat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
-def : ThumbPat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
-def : ThumbPat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>;
+def : TPat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
+def : TPat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
+def : TPat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>;
// Large immediate handling.
// Two piece imms.
-def : ThumbPat<(i32 thumb_immshifted:$src),
- (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
- (thumb_immshifted_shamt imm:$src))>;
+def : T1Pat<(i32 thumb_immshifted:$src),
+ (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)),
+ (thumb_immshifted_shamt imm:$src))>;
-def : ThumbPat<(i32 imm0_255_comp:$src),
- (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
+def : T1Pat<(i32 imm0_255_comp:$src),
+ (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index e0617e4..bfdf719 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -14,9 +14,9 @@
// Shifted operands. No register controlled shifts for Thumb2.
// Note: We do not support rrx shifted operands yet.
def t2_so_reg : Operand<i32>, // reg imm
- ComplexPattern<i32, 2, "SelectThumb2ShifterOperandReg",
+ ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
[shl,srl,sra,rotr]> {
- let PrintMethod = "printSOOperand";
+ let PrintMethod = "printT2SOOperand";
let MIOperandInfo = (ops GPR, i32imm);
}
@@ -69,6 +69,11 @@ def t2_so_imm_neg : Operand<i32>,
let PrintMethod = "printT2SOImmOperand";
}
+/// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
+def imm1_31 : PatLeaf<(i32 imm), [{
+ return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32;
+}]>;
+
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095 : PatLeaf<(i32 imm), [{
return (uint32_t)N->getZExtValue() < 4096;
@@ -121,137 +126,287 @@ def t2_lo16AllZero : PatLeaf<(i32 imm), [{
return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
}], t2_hi16>;
+
//===----------------------------------------------------------------------===//
-// Thumb2 to cover the functionality of the ARM instruction set.
+// Multiclass helpers...
//
-/// T2I_bin_is - Defines a set of (op reg, {so_imm|so_reg}) patterns for a
-// binary operation that produces a value.
-multiclass T2I_bin_is<string opc, PatFrag opnode> {
+/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
+/// unary operation that produces a value. These are predicable and can be
+/// changed to modify CPSR.
+multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{
// shifted imm
- def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
+ def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src),
+ opc, " $dst, $src",
+ [(set GPR:$dst, (opnode t2_so_imm:$src))]> {
+ let isAsCheapAsAMove = Cheap;
+ let isReMaterializable = ReMat;
+ }
+ // register
+ def r : T2I<(outs GPR:$dst), (ins GPR:$src),
+ opc, " $dst, $src",
+ [(set GPR:$dst, (opnode GPR:$src))]>;
// shifted register
- def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
+ def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src),
+ opc, " $dst, $src",
+ [(set GPR:$dst, (opnode t2_so_reg:$src))]>;
}
-/// T2I_2bin_is - Same as T2I_bin_is except the order of operands are reversed.
+/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
+// binary operation that produces a value. These are predicable and can be
+/// changed to modify CPSR.
+multiclass T2I_bin_irs<string opc, PatFrag opnode, bit Commutable = 0> {
+ // shifted imm
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
+ // register
+ def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
+ let isCommutable = Commutable;
+ }
+ // shifted register
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
+}
+
+/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
+/// reversed. It doesn't define the 'rr' form since it's handled by its
+/// T2I_bin_irs counterpart.
multiclass T2I_rbin_is<string opc, PatFrag opnode> {
// shifted imm
def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
+ opc, " $dst, $rhs, $lhs",
[(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
// shifted register
def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
+ opc, " $dst, $rhs, $lhs",
[(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
}
-/// T2I_bin_s_is - Similar to T2I_bin_is except it sets the 's' bit so the
+/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
/// instruction modifies the CPSR register.
let Defs = [CPSR] in {
-multiclass T2I_bin_s_is<string opc, PatFrag opnode> {
+multiclass T2I_bin_s_irs<string opc, PatFrag opnode, bit Commutable = 0> {
// shifted imm
def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
+ !strconcat(opc, "s"), " $dst, $lhs, $rhs",
[(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
-
+ // register
+ def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ !strconcat(opc, "s"), " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
+ let isCommutable = Commutable;
+ }
// shifted register
def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
+ !strconcat(opc, "s"), " $dst, $lhs, $rhs",
[(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
}
}
-/// T2I_rbin_s_is - Same as T2I_bin_s_is except the order of operands are
-/// reversed.
-let Defs = [CPSR] in {
-multiclass T2I_rbin_s_is<string opc, PatFrag opnode> {
+/// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
+/// patterns for a binary operation that produces a value.
+multiclass T2I_bin_ii12rs<string opc, PatFrag opnode, bit Commutable = 0> {
// shifted imm
- def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
-
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
+ // 12-bit imm
+ def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ !strconcat(opc, "w"), " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>;
+ // register
+ def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
+ let isCommutable = Commutable;
+ }
// shifted register
- def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
-}
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
}
-/// T2I_bin_ii12s - Defines a set of (op reg, {so_imm|imm0_4095|so_reg}) patterns
-/// for a binary operation that produces a value.
-multiclass T2I_bin_ii12s<string opc, PatFrag opnode> {
+/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
+/// binary operation that produces a value and use and define the carry bit.
+/// It's not predicable.
+let Uses = [CPSR] in {
+multiclass T2I_adde_sube_irs<string opc, PatFrag opnode, bit Commutable = 0> {
// shifted imm
- def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
- // 12-bit imm
- def ri12 : T2I<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
- !strconcat(opc, "w $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>;
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // register
+ def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]> {
+ let isCommutable = Commutable;
+ }
// shifted register
- def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
- !strconcat(opc, " $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // Carry setting variants
+ // shifted imm
+ def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ // register
+ def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ let isCommutable = Commutable;
+ }
+ // shifted register
+ def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+}
}
-/// T2I_bin_c_is - Defines a set of (op reg, {so_imm|reg}) patterns for a
-// binary operation that produces a value and set the carry bit. It can also
-/// optionally set CPSR.
-let Uses = [CPSR] in {
-multiclass T2I_bin_c_is<string opc, PatFrag opnode> {
+/// T2I_rsc_is - Same as T2I_adde_sube_irs except the order of operands are
+/// reversed. It doesn't define the 'rr' form since it's handled by its
+/// T2I_adde_sube_irs counterpart.
+let Defs = [CPSR], Uses = [CPSR] in {
+multiclass T2I_rsc_is<string opc, PatFrag opnode> {
// shifted imm
- def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs, cc_out:$s),
- !strconcat(opc, "${s} $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
-
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
+ opc, " $dst, $rhs, $lhs",
+ [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
// shifted register
- def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs, cc_out:$s),
- !strconcat(opc, "${s} $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
+ opc, " $dst, $rhs, $lhs",
+ [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // shifted imm
+ def Sri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
+ !strconcat(opc, "s $dst, $rhs, $lhs"),
+ [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ // shifted register
+ def Srs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
+ !strconcat(opc, "s $dst, $rhs, $lhs"),
+ [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
}
}
-/// T2I_rbin_c_is - Same as T2I_bin_c_is except the order of operands are
-/// reversed.
-let Uses = [CPSR] in {
-multiclass T2I_rbin_c_is<string opc, PatFrag opnode> {
+/// T2I_rbin_s_is - Same as T2I_bin_s_irs except the order of operands are
+/// reversed. It doesn't define the 'rr' form since it's handled by its
+/// T2I_bin_s_irs counterpart.
+let Defs = [CPSR] in {
+multiclass T2I_rbin_s_is<string opc, PatFrag opnode> {
// shifted imm
- def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s),
- !strconcat(opc, "${s} $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
-
+ def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s),
+ !strconcat(opc, "${s} $dst, $rhs, $lhs"),
+ [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
// shifted register
- def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s),
- !strconcat(opc, "${s} $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
+ def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s),
+ !strconcat(opc, "${s} $dst, $rhs, $lhs"),
+ [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
}
}
+/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
+// rotate operation that produces a value.
+multiclass T2I_sh_ir<string opc, PatFrag opnode> {
+ // 5-bit imm
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>;
+ // register
+ def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
+}
-/// T21_cmp_irs - Defines a set of (op r, {so_imm|so_reg}) cmp / test
-/// patterns. Similar to T2I_bin_is except the instruction does not produce
+/// T21_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
+/// patterns. Similar to T2I_bin_irs except the instruction does not produce
/// a explicit result, only implicitly set CPSR.
let Uses = [CPSR] in {
multiclass T2I_cmp_is<string opc, PatFrag opnode> {
// shifted imm
def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs),
- !strconcat(opc, " $lhs, $rhs"),
+ opc, " $lhs, $rhs",
[(opnode GPR:$lhs, t2_so_imm:$rhs)]>;
-
+ // register
+ def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $lhs, $rhs",
+ [(opnode GPR:$lhs, GPR:$rhs)]>;
// shifted register
def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs),
- !strconcat(opc, " $lhs, $rhs"),
+ opc, " $lhs, $rhs",
[(opnode GPR:$lhs, t2_so_reg:$rhs)]>;
}
}
//===----------------------------------------------------------------------===//
-// Arithmetic Instructions.
+// Instructions
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Miscellaneous Instructions.
+//
+
+let isNotDuplicable = 1 in
+def t2PICADD : T2XI<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp),
+ "$cp:\n\tadd $dst, pc",
+ [(set tGPR:$dst, (ARMpic_add tGPR:$lhs, imm:$cp))]>;
+
+
+// LEApcrel - Load a pc-relative address into a register without offending the
+// assembler.
+def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p),
+ !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
+ "${:private}PCRELL${:uid}+8))\n"),
+ !strconcat("${:private}PCRELL${:uid}:\n\t",
+ "add$p $dst, pc, #PCRELV${:uid}")),
+ []>;
+
+def t2LEApcrelJT : T2XI<(outs GPR:$dst),
+ (ins i32imm:$label, i32imm:$id, pred:$p),
+ !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
+ "${:private}PCRELL${:uid}+8))\n"),
+ !strconcat("${:private}PCRELL${:uid}:\n\t",
+ "add$p $dst, pc, #PCRELV${:uid}")),
+ []>;
+
+// ADD rd, sp, #so_imm
+def t2ADDrSPi : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
+ "add $dst, $sp, $imm",
+ []>;
+
+// ADD rd, sp, #imm12
+def t2ADDrSPi12 : T2XI<(outs GPR:$dst), (ins GPR:$sp, i32imm:$imm),
+ "addw $dst, $sp, $imm",
+ []>;
+
+def t2ADDrSPs : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
+ "addw $dst, $sp, $rhs",
+ []>;
+
+
+//===----------------------------------------------------------------------===//
+// Load / store Instructions.
//
//===----------------------------------------------------------------------===//
@@ -259,90 +414,95 @@ multiclass T2I_cmp_is<string opc, PatFrag opnode> {
//
let neverHasSideEffects = 1 in
-def t2MOVr : T2I<(outs GPR:$dst), (ins GPR:$src),
- "mov $dst, $src", []>;
+def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src),
+ "mov", " $dst, $src", []>;
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in
+def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src),
+ "mov", " $dst, $src",
+ [(set GPR:$dst, t2_so_imm:$src)]>;
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src),
- "movw $dst, $src",
+ "movw", " $dst, $src",
[(set GPR:$dst, imm0_65535:$src)]>;
-
-// FIXME: Move (shifted register) is a pseudo-instruction for ASR, LSL, LSR,
-// ROR, and RRX. Consider splitting into multiple instructions.
-def t2MOVs : T2I<(outs GPR:$dst), (ins t2_so_reg:$src),
- "mov $dst, $src",
- [(set GPR:$dst, t2_so_reg:$src)]>;
-def t2MOVrx : T2I<(outs GPR:$dst), (ins GPR:$src),
- "mov $dst, $src, rrx",
- [(set GPR:$dst, (ARMrrx GPR:$src))]>;
-
-
// FIXME: Also available in ARM mode.
let Constraints = "$src = $dst" in
-def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
- "movt $dst, $imm",
- [(set GPR:$dst,
- (or (and GPR:$src, 0xffff), t2_lo16AllZero:$imm))]>;
+def t2MOVTi16 : T2sI<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
+ "movt", " $dst, $imm",
+ [(set GPR:$dst,
+ (or (and GPR:$src, 0xffff), t2_lo16AllZero:$imm))]>;
//===----------------------------------------------------------------------===//
// Arithmetic Instructions.
//
-defm t2ADD : T2I_bin_ii12s<"add", BinOpFrag<(add node:$LHS, node:$RHS)>>;
-defm t2SUB : T2I_bin_ii12s<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
+defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
// ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
-defm t2ADDS : T2I_bin_s_is<"add", BinOpFrag<(addc node:$LHS, node:$RHS)>>;
-defm t2SUBS : T2I_bin_s_is<"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
+defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
-// FIXME: predication support
-defm t2ADC : T2I_bin_c_is<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
-defm t2SBC : T2I_bin_c_is<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>;
+defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// RSB, RSC
-defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
-defm t2RSBS : T2I_rbin_c_is<"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
-defm t2RSC : T2I_rbin_s_is<"rsc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+defm t2RSC : T2I_rsc_is <"rsc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
-def : Thumb2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
- (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
-def : Thumb2Pat<(add GPR:$src, imm0_4095_neg:$imm),
- (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
+def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
+ (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
+def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
+ (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
//===----------------------------------------------------------------------===//
+// Shift and rotate Instructions.
+//
+
+defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
+defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
+defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
+defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
+
+def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src),
+ "mov", " $dst, $src, rrx",
+ [(set GPR:$dst, (ARMrrx GPR:$src))]>;
+
+//===----------------------------------------------------------------------===//
// Bitwise Instructions.
//
-defm t2AND : T2I_bin_is <"and", BinOpFrag<(and node:$LHS, node:$RHS)>>;
-defm t2ORR : T2I_bin_is <"orr", BinOpFrag<(or node:$LHS, node:$RHS)>>;
-defm t2EOR : T2I_bin_is <"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
+defm t2AND : T2I_bin_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
+defm t2ORR : T2I_bin_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
+defm t2EOR : T2I_bin_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
-defm t2BIC : T2I_bin_is <"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
+defm t2BIC : T2I_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
-def : Thumb2Pat<(and GPR:$src, t2_so_imm_not:$imm),
- (t2BICri GPR:$src, t2_so_imm_not:$imm)>;
+def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm),
+ (t2BICri GPR:$src, t2_so_imm_not:$imm)>;
-defm t2ORN : T2I_bin_is <"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
+defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
-def : Thumb2Pat<(or GPR:$src, t2_so_imm_not:$imm),
- (t2ORNri GPR:$src, t2_so_imm_not:$imm)>;
+def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm),
+ (t2ORNri GPR:$src, t2_so_imm_not:$imm)>;
+// Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
+let AddedComplexity = 1 in
+defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>;
-def t2MVNr : T2I<(outs GPR:$dst), (ins t2_so_reg:$rhs),
- "mvn $dst, $rhs",
- [(set GPR:$dst, (not t2_so_reg:$rhs))]>;
-let isReMaterializable = 1, isAsCheapAsAMove = 1 in
-def t2MVNi : T2I<(outs GPR:$dst), (ins t2_so_imm_not:$rhs),
- "mvn $dst, $rhs",
- [(set GPR:$dst, t2_so_imm_not:$rhs)]>;
+def : T2Pat<(t2_so_imm_not:$src),
+ (t2MVNi t2_so_imm_not:$src)>;
// A8.6.17 BFC - Bitfield clear
// FIXME: Also available in ARM mode.
let Constraints = "$src = $dst" in
def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
- "bfc $dst, $imm",
+ "bfc", " $dst, $imm",
[(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
// FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
@@ -350,16 +510,17 @@ def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
//===----------------------------------------------------------------------===//
// Multiply Instructions.
//
+let isCommutable = 1 in
def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b),
- "mul $dst, $a, $b",
+ "mul", " $dst, $a, $b",
[(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
- "mla $dst, $a, $b, $c",
+ "mla", " $dst, $a, $b, $c",
[(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
- "mls $dst, $a, $b, $c",
+ "mls", " $dst, $a, $b, $c",
[(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>;
// FIXME: SMULL, etc.
@@ -368,20 +529,16 @@ def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
// Misc. Arithmetic Instructions.
//
-/////
-/// A8.6.31 CLZ
-/////
-// FIXME not firing? but ARM version does...
def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src),
- "clz $dst, $src",
+ "clz", " $dst, $src",
[(set GPR:$dst, (ctlz GPR:$src))]>;
def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src),
- "rev $dst, $src",
+ "rev", " $dst, $src",
[(set GPR:$dst, (bswap GPR:$src))]>;
def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src),
- "rev16 $dst, $src",
+ "rev16", " $dst, $src",
[(set GPR:$dst,
(or (and (srl GPR:$src, (i32 8)), 0xFF),
(or (and (shl GPR:$src, (i32 8)), 0xFF00),
@@ -392,7 +549,7 @@ def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src),
/// A8.6.137 REVSH
/////
def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src),
- "revsh $dst, $src",
+ "revsh", " $dst, $src",
[(set GPR:$dst,
(sext_inreg
(or (srl (and GPR:$src, 0xFFFF), (i32 8)),
@@ -414,11 +571,11 @@ defm t2CMN : T2I_cmp_is<"cmn",
defm t2CMNnz : T2I_cmp_is<"cmn",
BinOpFrag<(ARMcmpNZ node:$LHS,(ineg node:$RHS))>>;
-def : Thumb2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
- (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
+def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
+ (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
-def : Thumb2Pat<(ARMcmpNZ GPR:$src, t2_so_imm_neg:$imm),
- (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
+def : T2Pat<(ARMcmpNZ GPR:$src, t2_so_imm_neg:$imm),
+ (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
// FIXME: TST, TEQ, etc.
@@ -433,8 +590,13 @@ def : Thumb2Pat<(ARMcmpNZ GPR:$src, t2_so_imm_neg:$imm),
// Non-Instruction Patterns
//
+// ConstantPool, GlobalAddress, and JumpTable
+def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>;
+def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>;
+def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
+ (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
+
// Large immediate handling.
-def : Thumb2Pat<(i32 imm:$src),
- (t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)),
- (t2_hi16 imm:$src))>;
+def : T2Pat<(i32 imm:$src),
+ (t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>;
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp
index 42b8eae..bf2c14e 100644
--- a/lib/Target/ARM/ARMTargetAsmInfo.cpp
+++ b/lib/Target/ARM/ARMTargetAsmInfo.cpp
@@ -43,7 +43,7 @@ const char *const llvm::arm_asm_table[] = {
0,0
};
-ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM):
+ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM):
ARMTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
@@ -55,7 +55,7 @@ ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM):
SupportsDebugInformation = true;
}
-ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMTargetMachine &TM):
+ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM):
ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.h b/lib/Target/ARM/ARMTargetAsmInfo.h
index 683692f..d3f2da0 100644
--- a/lib/Target/ARM/ARMTargetAsmInfo.h
+++ b/lib/Target/ARM/ARMTargetAsmInfo.h
@@ -26,7 +26,7 @@ namespace llvm {
template <class BaseTAI>
struct ARMTargetAsmInfo : public BaseTAI {
- explicit ARMTargetAsmInfo(const ARMTargetMachine &TM) : BaseTAI(TM) {
+ explicit ARMTargetAsmInfo(const ARMBaseTargetMachine &TM) : BaseTAI(TM) {
BaseTAI::AsmTransCBE = arm_asm_table;
BaseTAI::AlignmentIsInBytes = false;
@@ -51,11 +51,11 @@ namespace llvm {
EXTERN_TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);
struct ARMDarwinTargetAsmInfo : public ARMTargetAsmInfo<DarwinTargetAsmInfo> {
- explicit ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM);
+ explicit ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM);
};
struct ARMELFTargetAsmInfo : public ARMTargetAsmInfo<ELFTargetAsmInfo> {
- explicit ARMELFTargetAsmInfo(const ARMTargetMachine &TM);
+ explicit ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM);
};
} // namespace llvm
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 8006b9b..f7b8215 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -39,13 +39,11 @@ int ARMTargetMachineModule = 0;
static RegisterTarget<ARMTargetMachine> X("arm", "ARM");
static RegisterTarget<ThumbTargetMachine> Y("thumb", "Thumb");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeARMTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeARMTarget() { }
// No assembler printer by default
-ARMTargetMachine::AsmPrinterCtorFn ARMTargetMachine::AsmPrinterCtor = 0;
+ARMBaseTargetMachine::AsmPrinterCtorFn ARMBaseTargetMachine::AsmPrinterCtor = 0;
/// ThumbTargetMachine - Create an Thumb architecture model.
///
@@ -76,34 +74,36 @@ unsigned ThumbTargetMachine::getModuleMatchQuality(const Module &M) {
return getJITMatchQuality()/2;
}
-ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
- : ARMTargetMachine(M, FS, true) {
-}
-
/// TargetMachine ctor - Create an ARM architecture model.
///
-ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS,
- bool isThumb)
+ARMBaseTargetMachine::ARMBaseTargetMachine(const Module &M,
+ const std::string &FS,
+ bool isThumb)
: Subtarget(M, FS, isThumb),
- DataLayout(Subtarget.isAPCS_ABI() ?
- // APCS ABI
- (isThumb ?
- std::string("e-p:32:32-f64:32:32-i64:32:32-"
- "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
- std::string("e-p:32:32-f64:32:32-i64:32:32")) :
- // AAPCS ABI
- (isThumb ?
- std::string("e-p:32:32-f64:64:64-i64:64:64-"
- "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
- std::string("e-p:32:32-f64:64:64-i64:64:64"))),
- InstrInfo(Subtarget),
FrameInfo(Subtarget),
JITInfo(),
- TLInfo(*this),
InstrItins(Subtarget.getInstrItineraryData()) {
DefRelocModel = getRelocationModel();
}
+ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
+ : ARMBaseTargetMachine(M, FS, false), InstrInfo(Subtarget),
+ DataLayout(Subtarget.isAPCS_ABI() ?
+ std::string("e-p:32:32-f64:32:32-i64:32:32") :
+ std::string("e-p:32:32-f64:64:64-i64:64:64")),
+ TLInfo(*this) {
+}
+
+ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
+ : ARMBaseTargetMachine(M, FS, true), InstrInfo(Subtarget),
+ DataLayout(Subtarget.isAPCS_ABI() ?
+ std::string("e-p:32:32-f64:32:32-i64:32:32-"
+ "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
+ std::string("e-p:32:32-f64:64:64-i64:64:64-"
+ "i16:16:32-i8:8:32-i1:8:32-a:0:32")),
+ TLInfo(*this) {
+}
+
unsigned ARMTargetMachine::getJITMatchQuality() {
#if defined(__arm__)
return 10;
@@ -131,7 +131,7 @@ unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
}
-const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
+const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
switch (Subtarget.TargetType) {
case ARMSubtarget::isDarwin:
return new ARMDarwinTargetAsmInfo(*this);
@@ -144,22 +144,22 @@ const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
// Pass Pipeline Configuration
-bool ARMTargetMachine::addInstSelector(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel) {
+bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
PM.add(createARMISelDag(*this));
return false;
}
-bool ARMTargetMachine::addPreRegAlloc(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel) {
+bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
// FIXME: temporarily disabling load / store optimization pass for Thumb mode.
if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
PM.add(createARMLoadStoreOptimizationPass(true));
return true;
}
-bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel) {
+bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
// FIXME: temporarily disabling load / store optimization pass for Thumb mode.
if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
PM.add(createARMLoadStoreOptimizationPass());
@@ -172,10 +172,10 @@ bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
return true;
}
-bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool Verbose,
- raw_ostream &Out) {
+bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool Verbose,
+ raw_ostream &Out) {
// Output assembly language.
assert(AsmPrinterCtor && "AsmPrinter was not linked in");
if (AsmPrinterCtor)
@@ -185,10 +185,10 @@ bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
}
-bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool DumpAsm,
- MachineCodeEmitter &MCE) {
+bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool DumpAsm,
+ MachineCodeEmitter &MCE) {
// FIXME: Move this to TargetJITInfo!
if (DefRelocModel == Reloc::Default)
setRelocationModel(Reloc::Static);
@@ -204,10 +204,10 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
return false;
}
-bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool DumpAsm,
- JITCodeEmitter &JCE) {
+bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool DumpAsm,
+ JITCodeEmitter &JCE) {
// FIXME: Move this to TargetJITInfo!
if (DefRelocModel == Reloc::Default)
setRelocationModel(Reloc::Static);
@@ -223,10 +223,10 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
return false;
}
-bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool DumpAsm,
- MachineCodeEmitter &MCE) {
+bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool DumpAsm,
+ MachineCodeEmitter &MCE) {
// Machine code emitter pass for ARM.
PM.add(createARMCodeEmitterPass(*this, MCE));
if (DumpAsm) {
@@ -238,10 +238,10 @@ bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
return false;
}
-bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool DumpAsm,
- JITCodeEmitter &JCE) {
+bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool DumpAsm,
+ JITCodeEmitter &JCE) {
// Machine code emitter pass for ARM.
PM.add(createARMJITCodeEmitterPass(*this, JCE));
if (DumpAsm) {
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index c4c8e6c..0b49b92 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -22,18 +22,19 @@
#include "ARMJITInfo.h"
#include "ARMSubtarget.h"
#include "ARMISelLowering.h"
+#include "ThumbInstrInfo.h"
namespace llvm {
class Module;
-class ARMTargetMachine : public LLVMTargetMachine {
+class ARMBaseTargetMachine : public LLVMTargetMachine {
+protected:
ARMSubtarget Subtarget;
- const TargetData DataLayout; // Calculates type size & alignment
- ARMInstrInfo InstrInfo;
+
+private:
ARMFrameInfo FrameInfo;
ARMJITInfo JITInfo;
- ARMTargetLowering TLInfo;
InstrItineraryData InstrItins;
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
@@ -41,26 +42,18 @@ protected:
// To avoid having target depend on the asmprinter stuff libraries, asmprinter
// set this functions to ctor pointer at startup time if they are linked in.
typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
- ARMTargetMachine &tm,
+ ARMBaseTargetMachine &tm,
CodeGenOpt::Level OptLevel,
bool verbose);
static AsmPrinterCtorFn AsmPrinterCtor;
public:
- ARMTargetMachine(const Module &M, const std::string &FS, bool isThumb = false);
+ ARMBaseTargetMachine(const Module &M, const std::string &FS, bool isThumb);
- virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
- virtual const ARMRegisterInfo *getRegisterInfo() const {
- return &InstrInfo.getRegisterInfo();
- }
- virtual const TargetData *getTargetData() const { return &DataLayout; }
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
- virtual ARMTargetLowering *getTargetLowering() const {
- return const_cast<ARMTargetLowering*>(&TLInfo);
- }
- virtual const InstrItineraryData getInstrItineraryData() const {
+ virtual const InstrItineraryData getInstrItineraryData() const {
return InstrItins;
}
@@ -94,12 +87,50 @@ public:
JITCodeEmitter &MCE);
};
+/// ARMTargetMachine - ARM target machine.
+///
+class ARMTargetMachine : public ARMBaseTargetMachine {
+ ARMInstrInfo InstrInfo;
+ const TargetData DataLayout; // Calculates type size & alignment
+ ARMTargetLowering TLInfo;
+public:
+ ARMTargetMachine(const Module &M, const std::string &FS);
+
+ virtual const ARMRegisterInfo *getRegisterInfo() const {
+ return &InstrInfo.getRegisterInfo();
+ }
+
+ virtual ARMTargetLowering *getTargetLowering() const {
+ return const_cast<ARMTargetLowering*>(&TLInfo);
+ }
+
+ virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
+ virtual const TargetData *getTargetData() const { return &DataLayout; }
+
+ static unsigned getJITMatchQuality();
+ static unsigned getModuleMatchQuality(const Module &M);
+};
+
/// ThumbTargetMachine - Thumb target machine.
///
-class ThumbTargetMachine : public ARMTargetMachine {
+class ThumbTargetMachine : public ARMBaseTargetMachine {
+ ThumbInstrInfo InstrInfo;
+ const TargetData DataLayout; // Calculates type size & alignment
+ ARMTargetLowering TLInfo;
public:
ThumbTargetMachine(const Module &M, const std::string &FS);
+ virtual const ARMRegisterInfo *getRegisterInfo() const {
+ return &InstrInfo.getRegisterInfo();
+ }
+
+ virtual ARMTargetLowering *getTargetLowering() const {
+ return const_cast<ARMTargetLowering*>(&TLInfo);
+ }
+
+ virtual const ThumbInstrInfo *getInstrInfo() const { return &InstrInfo; }
+ virtual const TargetData *getTargetData() const { return &DataLayout; }
+
static unsigned getJITMatchQuality();
static unsigned getModuleMatchQuality(const Module &M);
};
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
index fe1c980..400f628a 100644
--- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
@@ -21,6 +21,7 @@
#include "ARMMachineFunctionInfo.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -96,9 +97,7 @@ namespace {
const char *Modifier = 0);
void printSOImmOperand(const MachineInstr *MI, int opNum);
void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
- void printSOOperand(const MachineInstr *MI, int OpNum);
void printSORegOperand(const MachineInstr *MI, int opNum);
- void printT2SOImmOperand(const MachineInstr *MI, int opNum);
void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
@@ -110,6 +109,7 @@ namespace {
void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
const char *Modifier = 0);
void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNo);
+
void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
unsigned Scale);
@@ -117,6 +117,10 @@ namespace {
void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
+
+ void printT2SOImmOperand(const MachineInstr *MI, int opNum);
+ void printT2SOOperand(const MachineInstr *MI, int OpNum);
+
void printPredicateOperand(const MachineInstr *MI, int opNum);
void printSBitModifierOperand(const MachineInstr *MI, int opNum);
void printPCLabel(const MachineInstr *MI, int opNum);
@@ -169,11 +173,6 @@ namespace {
O << ")";
}
O << "\n";
-
- // If the constant pool value is a extern weak symbol, remember to emit
- // the weak reference.
- if (GV && GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
}
void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -331,8 +330,6 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
if (isCallOp && Subtarget->isTargetELF() &&
TM.getRelocationModel() == Reloc::PIC_)
O << "(PLT)";
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
break;
}
case MachineOperand::MO_ExternalSymbol: {
@@ -408,32 +405,10 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
}
-// Constant shifts so_reg is a 3-operand unit corresponding to register forms of
-// the A5.1 "Addressing Mode 1 - Data-processing operands" forms. This
-// includes:
-// REG 0 - e.g. R5
-// REG IMM, SH_OPC - e.g. R5, LSL #3
-void ARMAsmPrinter::printSOOperand(const MachineInstr *MI, int OpNum) {
- const MachineOperand &MO1 = MI->getOperand(OpNum);
- const MachineOperand &MO2 = MI->getOperand(OpNum+1);
-
- unsigned Reg = MO1.getReg();
- assert(TargetRegisterInfo::isPhysicalRegister(Reg));
- O << TM.getRegisterInfo()->getAsmName(Reg);
-
- // Print the shift opc.
- O << ", "
- << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
- << " ";
-
- assert(MO2.isImm() && "Not a valid t2_so_reg value!");
- O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
-}
-
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
-// REG 0 0 - e.g. R5
-// REG REG 0,SH_OPC - e.g. R5, ROR R3
+// REG 0 0 - e.g. R5
+// REG REG 0,SH_OPC - e.g. R5, ROR R3
// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
@@ -457,24 +432,6 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
}
}
-static void printT2SOImm(raw_ostream &O, int64_t V) {
- unsigned Imm = ARM_AM::getT2SOImmValDecode(V);
-
- // Always print the immediate directly, as the "rotate" form
- // is deprecated in some contexts.
- O << "#" << Imm;
-}
-
-/// printT2SOImmOperand - T2SOImm is:
-/// 1. a 4-bit splat control value and 8 bit immediate value
-/// 2. a 5-bit rotate amount and a non-zero 8-bit immediate value
-/// represented by a normalizedin 7-bit value (msb is always 1)
-void ARMAsmPrinter::printT2SOImmOperand(const MachineInstr *MI, int OpNum) {
- const MachineOperand &MO = MI->getOperand(OpNum);
- assert(MO.isImm() && "Not a valid so_imm value!");
- printT2SOImm(O, MO.getImm());
-}
-
void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
@@ -643,8 +600,8 @@ void
ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) {
const MachineOperand &MO = MI->getOperand(Op);
uint32_t v = ~MO.getImm();
- int32_t lsb = ffs (v) - 1;
- int32_t width = fls (v) - lsb;
+ int32_t lsb = CountTrailingZeros_32(v);
+ int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
O << "#" << lsb << ", #" << width;
}
@@ -702,6 +659,42 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
O << "]";
}
+/// printT2SOImmOperand - T2SOImm is:
+/// 1. a 4-bit splat control value and 8 bit immediate value
+/// 2. a 5-bit rotate amount and a non-zero 8-bit immediate value
+/// represented by a normalizedin 7-bit value (msb is always 1)
+void ARMAsmPrinter::printT2SOImmOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImm() && "Not a valid so_imm value!");
+
+ unsigned Imm = ARM_AM::getT2SOImmValDecode(MO.getImm());
+ // Always print the immediate directly, as the "rotate" form
+ // is deprecated in some contexts.
+ O << "#" << Imm;
+}
+
+// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
+// register with shift forms.
+// REG 0 0 - e.g. R5
+// REG IMM, SH_OPC - e.g. R5, LSL #3
+void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO1 = MI->getOperand(OpNum);
+ const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+
+ unsigned Reg = MO1.getReg();
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+ O << TM.getRegisterInfo()->getAsmName(Reg);
+
+ // Print the shift opc.
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
+ << " ";
+
+ assert(MO2.isImm() && "Not a valid t2_so_reg value!");
+ O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
+}
+
+
void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
if (CC != ARMCC::AL)
@@ -749,10 +742,6 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
} else {
EmitGlobalConstant(MCPE.Val.ConstVal);
- // remember to emit the weak reference
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
}
}
}
@@ -934,6 +923,8 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -1046,12 +1037,6 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
if (TAI->hasDotTypeDotSizeDirective())
O << "\t.size " << name << ", " << Size << "\n";
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
O << '\n';
}
@@ -1135,18 +1120,12 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
}
- // Emit initial debug information.
- DW->EndModule();
-
// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
O << "\t.subsections_via_symbols\n";
- } else {
- // Emit final debug information for ELF.
- DW->EndModule();
}
return AsmPrinter::doFinalization(M);
@@ -1158,7 +1137,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
- ARMTargetMachine &tm,
+ ARMBaseTargetMachine &tm,
CodeGenOpt::Level OptLevel,
bool verbose) {
return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
@@ -1167,13 +1146,10 @@ FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
namespace {
static struct Register {
Register() {
- ARMTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
+ ARMBaseTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
}
} Registrator;
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeARMAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeARMAsmPrinter() { }
diff --git a/lib/Target/ARM/AsmPrinter/CMakeLists.txt b/lib/Target/ARM/AsmPrinter/CMakeLists.txt
index c22964f..a67fc84 100644
--- a/lib/Target/ARM/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/ARM/AsmPrinter/CMakeLists.txt
@@ -3,3 +3,4 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMARMAsmPrinter
ARMAsmPrinter.cpp
)
+add_dependencies(LLVMARMAsmPrinter ARMCodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt
index 2ac40f5..e665ed9 100644
--- a/lib/Target/ARM/CMakeLists.txt
+++ b/lib/Target/ARM/CMakeLists.txt
@@ -24,4 +24,5 @@ add_llvm_target(ARMCodeGen
ARMSubtarget.cpp
ARMTargetAsmInfo.cpp
ARMTargetMachine.cpp
+ ThumbInstrInfo.cpp
)
diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt
index 0252a4a..4223699 100644
--- a/lib/Target/ARM/README.txt
+++ b/lib/Target/ARM/README.txt
@@ -96,20 +96,7 @@ Which would be better. This occurs in png decode.
//===---------------------------------------------------------------------===//
More load / store optimizations:
-1) Look past instructions without side-effects (not load, store, branch, etc.)
- when forming the list of loads / stores to optimize.
-
-2) Smarter register allocation?
-We are probably missing some opportunities to use ldm / stm. Consider:
-
-ldr r5, [r0]
-ldr r4, [r0, #4]
-
-This cannot be merged into a ldm. Perhaps we will need to do the transformation
-before register allocation. Then teach the register allocator to allocate a
-chunk of consecutive registers.
-
-3) Better representation for block transfer? This is from Olden/power:
+1) Better representation for block transfer? This is from Olden/power:
fldd d0, [r4]
fstd d0, [r4, #+32]
@@ -123,7 +110,7 @@ chunk of consecutive registers.
If we can spare the registers, it would be better to use fldm and fstm here.
Need major register allocator enhancement though.
-4) Can we recognize the relative position of constantpool entries? i.e. Treat
+2) Can we recognize the relative position of constantpool entries? i.e. Treat
ldr r0, LCPI17_3
ldr r1, LCPI17_4
@@ -147,13 +134,7 @@ L6:
.long -858993459
.long 1074318540
-5) Can we make use of ldrd and strd? Instead of generating ldm / stm, use
-ldrd/strd instead if there are only two destination registers that form an
-odd/even pair. However, we probably would pay a penalty if the address is not
-aligned on 8-byte boundary. This requires more information on load / store
-nodes (and MI's?) then we currently carry.
-
-6) struct copies appear to be done field by field
+3) struct copies appear to be done field by field
instead of by words, at least sometimes:
struct foo { int x; short s; char c1; char c2; };
@@ -313,11 +294,6 @@ See McCat/18-imp/ComputeBoundingBoxes for an example.
//===---------------------------------------------------------------------===//
-Register scavenging is now implemented. The example in the previous version
-of this document produces optimal code at -O2.
-
-//===---------------------------------------------------------------------===//
-
Pre-/post- indexed load / stores:
1) We should not make the pre/post- indexed load/store transform if the base ptr
@@ -353,20 +329,6 @@ time.
//===---------------------------------------------------------------------===//
-We should add i64 support to take advantage of the 64-bit load / stores.
-We can add a pseudo i64 register class containing pseudo registers that are
-register pairs. All other ops (e.g. add, sub) would be expanded as usual.
-
-We need to add pseudo instructions (i.e. gethi / getlo) to extract i32 registers
-from the i64 register. These are single moves which can be eliminated if the
-destination register is a sub-register of the source. We should implement proper
-subreg support in the register allocator to coalesce these away.
-
-There are other minor issues such as multiple instructions for a spill / restore
-/ move.
-
-//===---------------------------------------------------------------------===//
-
Implement support for some more tricky ways to materialize immediates. For
example, to get 0xffff8000, we can use:
@@ -465,12 +427,6 @@ More register scavenging work:
1. Use the register scavenger to track frame index materialized into registers
(those that do not fit in addressing modes) to allow reuse in the same BB.
2. Finish scavenging for Thumb.
-3. We know some spills and restores are unnecessary. The issue is once live
- intervals are merged, they are not never split. So every def is spilled
- and every use requires a restore if the register allocator decides the
- resulting live interval is not assigned a physical register. It may be
- possible (with the help of the scavenger) to turn some spill / restore
- pairs into register copies.
//===---------------------------------------------------------------------===//
@@ -572,3 +528,5 @@ those operations and the ARMv6 scalar versions.
//===---------------------------------------------------------------------===//
+ARM::MOVCCr is commutable (by flipping the condition). But we need to implement
+ARMInstrInfo::commuteInstruction() to support it.
diff --git a/lib/Target/ARM/ThumbInstrInfo.cpp b/lib/Target/ARM/ThumbInstrInfo.cpp
new file mode 100644
index 0000000..075d940
--- /dev/null
+++ b/lib/Target/ARM/ThumbInstrInfo.cpp
@@ -0,0 +1,282 @@
+//===- ThumbInstrInfo.cpp - Thumb Instruction Information --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Thumb implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMInstrInfo.h"
+#include "ARM.h"
+#include "ARMGenInstrInfo.inc"
+#include "ARMMachineFunctionInfo.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/ADT/SmallVector.h"
+#include "ThumbInstrInfo.h"
+
+using namespace llvm;
+
+ThumbInstrInfo::ThumbInstrInfo(const ARMSubtarget &STI)
+ : ARMBaseInstrInfo(STI) {
+}
+
+bool ThumbInstrInfo::isMoveInstr(const MachineInstr &MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
+ SrcSubIdx = DstSubIdx = 0; // No sub-registers.
+
+ unsigned oc = MI.getOpcode();
+ switch (oc) {
+ default:
+ return false;
+ // FIXME: Thumb2
+ case ARM::tMOVr:
+ case ARM::tMOVhir2lor:
+ case ARM::tMOVlor2hir:
+ case ARM::tMOVhir2hir:
+ assert(MI.getDesc().getNumOperands() >= 2 &&
+ MI.getOperand(0).isReg() &&
+ MI.getOperand(1).isReg() &&
+ "Invalid Thumb MOV instruction");
+ SrcReg = MI.getOperand(1).getReg();
+ DstReg = MI.getOperand(0).getReg();
+ return true;
+ }
+}
+
+unsigned ThumbInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ // FIXME: Thumb2
+ case ARM::tRestore:
+ if (MI->getOperand(1).isFI() &&
+ MI->getOperand(2).isImm() &&
+ MI->getOperand(2).getImm() == 0) {
+ FrameIndex = MI->getOperand(1).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+unsigned ThumbInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ // FIXME: Thumb2
+ case ARM::tSpill:
+ if (MI->getOperand(1).isFI() &&
+ MI->getOperand(2).isImm() &&
+ MI->getOperand(2).getImm() == 0) {
+ FrameIndex = MI->getOperand(1).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+bool ThumbInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC) const {
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (I != MBB.end()) DL = I->getDebugLoc();
+
+ // FIXME: Thumb2
+ if (DestRC == ARM::GPRRegisterClass) {
+ if (SrcRC == ARM::GPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg);
+ return true;
+ } else if (SrcRC == ARM::tGPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
+ return true;
+ }
+ } else if (DestRC == ARM::tGPRRegisterClass) {
+ if (SrcRC == ARM::GPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
+ return true;
+ } else if (SrcRC == ARM::tGPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ThumbInstrInfo::
+storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill, int FI,
+ const TargetRegisterClass *RC) const {
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (I != MBB.end()) DL = I->getDebugLoc();
+
+ assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
+
+ // FIXME: Thumb2
+ if (RC == ARM::tGPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tSpill))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FI).addImm(0);
+ }
+}
+
+void ThumbInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
+ bool isKill,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs) const{
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ unsigned Opc = 0;
+
+ // FIXME: Thumb2. Is GPRRegClass here correct?
+ assert(RC == ARM::GPRRegisterClass && "Unknown regclass!");
+ if (RC == ARM::GPRRegisterClass) {
+ Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
+ }
+
+ MachineInstrBuilder MIB =
+ BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
+ for (unsigned i = 0, e = Addr.size(); i != e; ++i)
+ MIB.addOperand(Addr[i]);
+ NewMIs.push_back(MIB);
+ return;
+}
+
+void ThumbInstrInfo::
+loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned DestReg, int FI,
+ const TargetRegisterClass *RC) const {
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (I != MBB.end()) DL = I->getDebugLoc();
+
+ // FIXME: Thumb2
+ assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
+
+ if (RC == ARM::tGPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
+ .addFrameIndex(FI).addImm(0);
+ }
+}
+
+void ThumbInstrInfo::
+loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs) const {
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ unsigned Opc = 0;
+
+ // FIXME: Thumb2. Is GPRRegClass ok here?
+ if (RC == ARM::GPRRegisterClass) {
+ Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
+ }
+
+ MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
+ for (unsigned i = 0, e = Addr.size(); i != e; ++i)
+ MIB.addOperand(Addr[i]);
+ NewMIs.push_back(MIB);
+ return;
+}
+
+bool ThumbInstrInfo::
+spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI) const {
+ if (CSI.empty())
+ return false;
+
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
+ for (unsigned i = CSI.size(); i != 0; --i) {
+ unsigned Reg = CSI[i-1].getReg();
+ // Add the callee-saved register as live-in. It's killed at the spill.
+ MBB.addLiveIn(Reg);
+ MIB.addReg(Reg, RegState::Kill);
+ }
+ return true;
+}
+
+bool ThumbInstrInfo::
+restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI) const {
+ MachineFunction &MF = *MBB.getParent();
+ ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ if (CSI.empty())
+ return false;
+
+ bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
+ MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
+ for (unsigned i = CSI.size(); i != 0; --i) {
+ unsigned Reg = CSI[i-1].getReg();
+ if (Reg == ARM::LR) {
+ // Special epilogue for vararg functions. See emitEpilogue
+ if (isVarArg)
+ continue;
+ Reg = ARM::PC;
+ PopMI->setDesc(get(ARM::tPOP_RET));
+ MI = MBB.erase(MI);
+ }
+ PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
+ }
+
+ // It's illegal to emit pop instruction without operands.
+ if (PopMI->getNumOperands() > 0)
+ MBB.insert(MI, PopMI);
+
+ return true;
+}
+
+MachineInstr *ThumbInstrInfo::
+foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
+ const SmallVectorImpl<unsigned> &Ops, int FI) const {
+ if (Ops.size() != 1) return NULL;
+ const ARMRegisterInfo &RI = getRegisterInfo();
+
+ unsigned OpNum = Ops[0];
+ unsigned Opc = MI->getOpcode();
+ MachineInstr *NewMI = NULL;
+ switch (Opc) {
+ default: break;
+ case ARM::tMOVr:
+ case ARM::tMOVlor2hir:
+ case ARM::tMOVhir2lor:
+ case ARM::tMOVhir2hir: {
+ if (OpNum == 0) { // move -> store
+ unsigned SrcReg = MI->getOperand(1).getReg();
+ bool isKill = MI->getOperand(1).isKill();
+ if (RI.isPhysicalRegister(SrcReg) && !RI.isLowRegister(SrcReg))
+ // tSpill cannot take a high register operand.
+ break;
+ NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FI).addImm(0);
+ } else { // move -> load
+ unsigned DstReg = MI->getOperand(0).getReg();
+ if (RI.isPhysicalRegister(DstReg) && !RI.isLowRegister(DstReg))
+ // tRestore cannot target a high register operand.
+ break;
+ bool isDead = MI->getOperand(0).isDead();
+ NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
+ .addReg(DstReg, RegState::Define | getDeadRegState(isDead))
+ .addFrameIndex(FI).addImm(0);
+ }
+ break;
+ }
+ }
+
+ return NewMI;
+}
diff --git a/lib/Target/ARM/ThumbInstrInfo.h b/lib/Target/ARM/ThumbInstrInfo.h
new file mode 100644
index 0000000..dcf1095
--- /dev/null
+++ b/lib/Target/ARM/ThumbInstrInfo.h
@@ -0,0 +1,85 @@
+//===- ThumbInstrInfo.h - Thumb Instruction Information ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARM implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef THUMBINSTRUCTIONINFO_H
+#define THUMBINSTRUCTIONINFO_H
+
+#include "llvm/Target/TargetInstrInfo.h"
+#include "ARMRegisterInfo.h"
+#include "ARM.h"
+#include "ARMInstrInfo.h"
+
+namespace llvm {
+ class ARMSubtarget;
+
+class ThumbInstrInfo : public ARMBaseInstrInfo {
+public:
+ explicit ThumbInstrInfo(const ARMSubtarget &STI);
+
+ /// Return true if the instruction is a register to register move and return
+ /// the source and dest operands and their sub-register indices by reference.
+ virtual bool isMoveInstr(const MachineInstr &MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
+
+ virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+ virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+
+ virtual bool copyRegToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC) const;
+ virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC) const;
+
+ virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs) const;
+
+ virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC) const;
+
+ virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs) const;
+ virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI) const;
+ virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI) const;
+
+ virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
+ MachineInstr* MI,
+ const SmallVectorImpl<unsigned> &Ops,
+ MachineInstr* LoadMI) const {
+ return 0;
+ }
+
+ virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
+ MachineInstr* MI,
+ const SmallVectorImpl<unsigned> &Ops,
+ int FrameIndex) const;
+};
+}
+
+#endif // THUMBINSTRUCTIONINFO_H
diff --git a/lib/Target/Alpha/AlphaJITInfo.cpp b/lib/Target/Alpha/AlphaJITInfo.cpp
index 3fecb19..ba7478e 100644
--- a/lib/Target/Alpha/AlphaJITInfo.cpp
+++ b/lib/Target/Alpha/AlphaJITInfo.cpp
@@ -19,7 +19,6 @@
#include "llvm/Config/alloca.h"
#include "llvm/Support/Debug.h"
#include <cstdlib>
-#include <map>
using namespace llvm;
#define BUILD_OFormatI(Op, RA, LIT, FUN, RC) \
@@ -237,11 +236,6 @@ static long getLower16(long l)
void AlphaJITInfo::relocate(void *Function, MachineRelocation *MR,
unsigned NumRelocs, unsigned char* GOTBase) {
- //because gpdist are paired and relative to the pc of the first inst,
- //we need to have some state
-
- static std::map<std::pair<void*, int>, void*> gpdistmap;
-
for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4;
long idx = 0;
diff --git a/lib/Target/Alpha/AlphaJITInfo.h b/lib/Target/Alpha/AlphaJITInfo.h
index edff990..ecb467f 100644
--- a/lib/Target/Alpha/AlphaJITInfo.h
+++ b/lib/Target/Alpha/AlphaJITInfo.h
@@ -15,6 +15,7 @@
#define ALPHA_JITINFO_H
#include "llvm/Target/TargetJITInfo.h"
+#include <map>
namespace llvm {
class TargetMachine;
@@ -22,6 +23,10 @@ namespace llvm {
class AlphaJITInfo : public TargetJITInfo {
protected:
TargetMachine &TM;
+
+ //because gpdist are paired and relative to the pc of the first inst,
+ //we need to have some state
+ std::map<std::pair<void*, int>, void*> gpdistmap;
public:
explicit AlphaJITInfo(TargetMachine &tm) : TM(tm)
{ useGOT = true; }
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp
index feee6e4..0ff53c7 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.cpp
+++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp
@@ -54,7 +54,7 @@ static long getLower16(long l)
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
- TII(tii)
+ TII(tii), curgpdist(0)
{
}
@@ -206,8 +206,6 @@ void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const {
MBBI->getDebugLoc() : DebugLoc::getUnknownLoc());
bool FP = hasFP(MF);
- static int curgpdist = 0;
-
//handle GOP offset
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAHg), Alpha::R29)
.addGlobalAddress(const_cast<Function*>(MF.getFunction()))
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h
index c4f5f7b..5012fe8 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.h
+++ b/lib/Target/Alpha/AlphaRegisterInfo.h
@@ -60,6 +60,9 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
static std::string getPrettyName(unsigned reg);
+
+private:
+ mutable int curgpdist;
};
} // end namespace llvm
diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp
index cdd4fa4..10952eb 100644
--- a/lib/Target/Alpha/AlphaTargetMachine.cpp
+++ b/lib/Target/Alpha/AlphaTargetMachine.cpp
@@ -27,10 +27,8 @@ static RegisterTarget<AlphaTargetMachine> X("alpha", "Alpha [experimental]");
// No assembler printer by default
AlphaTargetMachine::AsmPrinterCtorFn AlphaTargetMachine::AsmPrinterCtor = 0;
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeAlphaTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeAlphaTarget() { }
const TargetAsmInfo *AlphaTargetMachine::createTargetAsmInfo() const {
return new AlphaTargetAsmInfo(*this);
diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
index 7b73bb3..e0c0a64 100644
--- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
+++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
@@ -17,6 +17,7 @@
#include "AlphaInstrInfo.h"
#include "AlphaTargetMachine.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Type.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
@@ -121,8 +122,6 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
case MachineOperand::MO_GlobalAddress: {
GlobalValue *GV = MO.getGlobal();
O << Mang->getValueName(GV);
- if (GV->isDeclaration() && GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
@@ -224,6 +223,8 @@ void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
unsigned Size = TD->getTypeAllocSize(C->getType());
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -265,12 +266,6 @@ void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
O << name << ":\n";
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
O << '\n';
}
@@ -304,11 +299,8 @@ bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeAlphaAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeAlphaAsmPrinter() { }
namespace {
static struct Register {
diff --git a/lib/Target/Alpha/AsmPrinter/CMakeLists.txt b/lib/Target/Alpha/AsmPrinter/CMakeLists.txt
index bf04762..992c218 100644
--- a/lib/Target/Alpha/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/Alpha/AsmPrinter/CMakeLists.txt
@@ -3,3 +3,4 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMAlphaAsmPrinter
AlphaAsmPrinter.cpp
)
+add_dependencies(LLVMAlphaAsmPrinter AlphaCodeGenTable_gen)
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index c3554f6..294c6d3 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -59,10 +59,8 @@ int CBackendTargetMachineModule = 0;
// Register the target.
static RegisterTarget<CTargetMachine> X("c", "C backend");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeCBackendTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeCBackendTarget() { }
namespace {
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
@@ -102,12 +100,13 @@ namespace {
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
std::set<const Argument*> ByValParams;
unsigned FPCounter;
+ unsigned OpaqueCounter;
public:
static char ID;
explicit CWriter(raw_ostream &o)
: FunctionPass(&ID), Out(o), IL(0), Mang(0), LI(0),
- TheModule(0), TAsm(0), TD(0) {
+ TheModule(0), TAsm(0), TD(0), OpaqueCounter(0) {
FPCounter = 0;
}
@@ -647,8 +646,7 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
}
case Type::OpaqueTyID: {
- static int Count = 0;
- std::string TyName = "struct opaque_" + itostr(Count++);
+ std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
assert(TypeNames.find(Ty) == TypeNames.end());
TypeNames[Ty] = TyName;
return Out << TyName << ' ' << NameSoFar;
@@ -752,8 +750,7 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
}
case Type::OpaqueTyID: {
- static int Count = 0;
- std::string TyName = "struct opaque_" + itostr(Count++);
+ std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
assert(TypeNames.find(Ty) == TypeNames.end());
TypeNames[Ty] = TyName;
return Out << TyName << ' ' << NameSoFar;
diff --git a/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt b/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt
index 0dad083..9684e63 100644
--- a/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt
@@ -6,3 +6,4 @@ include_directories(
add_llvm_library(LLVMCellSPUAsmPrinter
SPUAsmPrinter.cpp
)
+add_dependencies(LLVMCellSPUAsmPrinter CellSPUCodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
index 26a8ece..02b625b 100644
--- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
+++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
@@ -19,6 +19,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
@@ -361,9 +362,6 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
}
}
O << Name;
-
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
@@ -524,6 +522,8 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
printVisibility(name, GVar->getVisibility());
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -584,12 +584,6 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
PrintUnmangledNameSafely(GVar, O);
O << "'\n";
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
O << '\n';
}
@@ -600,9 +594,6 @@ bool LinuxAsmPrinter::doFinalization(Module &M) {
I != E; ++I)
printModuleLevelGV(I);
- // Emit initial debug information.
- DW->EndModule();
-
return AsmPrinter::doFinalization(M);
}
@@ -617,11 +608,8 @@ FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeCellSPUAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
namespace {
static struct Register {
diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp
index c675ebb..256d63d 100644
--- a/lib/Target/CellSPU/SPUTargetMachine.cpp
+++ b/lib/Target/CellSPU/SPUTargetMachine.cpp
@@ -32,10 +32,8 @@ namespace {
// No assembler printer by default
SPUTargetMachine::AsmPrinterCtorFn SPUTargetMachine::AsmPrinterCtor = 0;
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeCellSPUTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUTarget() { }
const std::pair<unsigned, int> *
SPUFrameInfo::getCalleeSaveSpillSlots(unsigned &NumEntries) const {
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 1feea96..28f58e8 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -82,10 +82,8 @@ int CppBackendTargetMachineModule = 0;
// Register the target.
static RegisterTarget<CPPTargetMachine> X("cpp", "C++ backend");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeCppBackendTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeCppBackendTarget() { }
namespace {
typedef std::vector<const Type*> TypeList;
@@ -1836,7 +1834,9 @@ namespace {
const std::string& mName) {
nl(Out) << "Module* " << fname << "() {";
nl(Out,1) << "// Module Construction";
- nl(Out) << "Module* mod = new Module(\"" << mName << "\");";
+ nl(Out) << "Module* mod = new Module(\"";
+ printEscapedString(mName);
+ Out << "\");";
if (!TheModule->getTargetTriple().empty()) {
nl(Out) << "mod->setDataLayout(\"" << TheModule->getDataLayout() << "\");";
}
@@ -1869,7 +1869,9 @@ namespace {
void CppWriter::printContents(const std::string& fname,
const std::string& mName) {
Out << "\nModule* " << fname << "(Module *mod) {\n";
- Out << "\nmod->setModuleIdentifier(\"" << mName << "\");\n";
+ Out << "\nmod->setModuleIdentifier(\"";
+ printEscapedString(mName);
+ Out << "\");\n";
printModuleBody();
Out << "\nreturn mod;\n";
Out << "\n}\n";
diff --git a/lib/Target/IA64/AsmPrinter/CMakeLists.txt b/lib/Target/IA64/AsmPrinter/CMakeLists.txt
index b81ed4a..ffe0eed 100644
--- a/lib/Target/IA64/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/IA64/AsmPrinter/CMakeLists.txt
@@ -6,3 +6,4 @@ include_directories(
add_llvm_library(LLVMIA64AsmPrinter
IA64AsmPrinter.cpp
)
+add_dependencies(LLVMIA64AsmPrinter IA64CodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp b/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
index 662c667..6b34a4e 100644
--- a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
+++ b/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
@@ -20,6 +20,7 @@
#include "IA64.h"
#include "IA64TargetMachine.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
@@ -269,6 +270,8 @@ void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
O << "\n\n";
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
unsigned Size = TD->getTypeAllocSize(C->getType());
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -384,8 +387,5 @@ namespace {
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeIA64AsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeIA64AsmPrinter() { }
diff --git a/lib/Target/IA64/IA64TargetMachine.cpp b/lib/Target/IA64/IA64TargetMachine.cpp
index 0b93ee5..4b05e1d 100644
--- a/lib/Target/IA64/IA64TargetMachine.cpp
+++ b/lib/Target/IA64/IA64TargetMachine.cpp
@@ -26,10 +26,8 @@ static RegisterTarget<IA64TargetMachine> X("ia64",
// No assembler printer by default
IA64TargetMachine::AsmPrinterCtorFn IA64TargetMachine::AsmPrinterCtor = 0;
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeIA64Target() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeIA64Target() { }
const TargetAsmInfo *IA64TargetMachine::createTargetAsmInfo() const {
return new IA64TargetAsmInfo(*this);
diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp
index 0aff14f..ee73c38 100644
--- a/lib/Target/MSIL/MSILWriter.cpp
+++ b/lib/Target/MSIL/MSILWriter.cpp
@@ -55,10 +55,8 @@ int MSILTargetMachineModule = 0;
static RegisterTarget<MSILTarget> X("msil", "MSIL backend");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeMSILTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeMSILTarget() { }
bool MSILModule::runOnModule(Module &M) {
ModulePtr = &M;
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 0f5244d..b1fe758 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -35,10 +35,8 @@ int MSP430TargetMachineModule = 0;
static RegisterTarget<MSP430TargetMachine>
X("msp430", "MSP430 [experimental]");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeMSP430Target() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeMSP430Target() { }
MSP430TargetMachine::MSP430TargetMachine(const Module &M,
const std::string &FS) :
diff --git a/lib/Target/Mips/AsmPrinter/CMakeLists.txt b/lib/Target/Mips/AsmPrinter/CMakeLists.txt
index 942548d..197cc29 100644
--- a/lib/Target/Mips/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/Mips/AsmPrinter/CMakeLists.txt
@@ -6,3 +6,4 @@ include_directories(
add_llvm_library(LLVMMipsAsmPrinter
MipsAsmPrinter.cpp
)
+add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
index 077ec96..431630b 100644
--- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
@@ -22,6 +22,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -483,6 +484,8 @@ printModuleLevelGV(const GlobalVariable* GVar) {
O << "\n\n";
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *CTy = C->getType();
unsigned Size = TD->getTypeAllocSize(CTy);
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
@@ -587,8 +590,5 @@ namespace {
} Registrator;
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeMipsAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeMipsAsmPrinter() { }
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 83b9b62..c5f117b 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -34,10 +34,8 @@ static RegisterTarget<MipselTargetMachine> Y("mipsel", "Mipsel");
MipsTargetMachine::AsmPrinterCtorFn MipsTargetMachine::AsmPrinterCtor = 0;
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeMipsTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeMipsTarget() { }
const TargetAsmInfo *MipsTargetMachine::
createTargetAsmInfo() const
diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp
index 27551cd..4300588 100644
--- a/lib/Target/PIC16/PIC16DebugInfo.cpp
+++ b/lib/Target/PIC16/PIC16DebugInfo.cpp
@@ -300,7 +300,7 @@ void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy,
// Get mangleddd name for this structure/union element.
std::string MangMemName = ElementName + UniqueSuffix;
PopulateDebugInfo(DITy, TypeNo, HasAux, ElementAux, TagName);
- short Class;
+ short Class = 0;
if( CTy.getTag() == dwarf::DW_TAG_union_type)
Class = PIC16Dbg::C_MOU;
else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
index 122af70..ec1db90 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.cpp
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -97,6 +97,16 @@ static const char *getIntrinsicName(unsigned opcode) {
case RTLIB::SUB_F32: Basename = "sub.f32"; break;
case RTLIB::MUL_F32: Basename = "mul.f32"; break;
case RTLIB::DIV_F32: Basename = "div.f32"; break;
+
+ // Floating point comparison
+ case RTLIB::O_F32: Basename = "unordered.f32"; break;
+ case RTLIB::UO_F32: Basename = "unordered.f32"; break;
+ case RTLIB::OLE_F32: Basename = "le.f32"; break;
+ case RTLIB::OGE_F32: Basename = "ge.f32"; break;
+ case RTLIB::OLT_F32: Basename = "lt.f32"; break;
+ case RTLIB::OGT_F32: Basename = "gt.f32"; break;
+ case RTLIB::OEQ_F32: Basename = "eq.f32"; break;
+ case RTLIB::UNE_F32: Basename = "neq.f32"; break;
}
std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
@@ -187,6 +197,25 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32));
setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32));
+ // Floationg point comparison
+ setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32));
+ setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32));
+ setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32));
+ setLibcallName(RTLIB::OLT_F32, getIntrinsicName(RTLIB::OLT_F32));
+ setLibcallName(RTLIB::OGT_F32, getIntrinsicName(RTLIB::OGT_F32));
+ setLibcallName(RTLIB::OEQ_F32, getIntrinsicName(RTLIB::OEQ_F32));
+ setLibcallName(RTLIB::UNE_F32, getIntrinsicName(RTLIB::UNE_F32));
+
+ // Return value comparisons of floating point calls.
+ setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ);
+
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
diff --git a/lib/Target/PIC16/PIC16MemSelOpt.cpp b/lib/Target/PIC16/PIC16MemSelOpt.cpp
index 20f926d..43d47ae 100644
--- a/lib/Target/PIC16/PIC16MemSelOpt.cpp
+++ b/lib/Target/PIC16/PIC16MemSelOpt.cpp
@@ -109,7 +109,7 @@ bool MemSelOpt::processInstruction(MachineInstr *MI) {
// If this insn is not going to access any memory, return.
const TargetInstrDesc &TID = TII->get(MI->getOpcode());
- if (! (TID.isCall() || TID.mayLoad() || TID.mayStore()))
+ if (!(TID.isBranch() || TID.isCall() || TID.mayLoad() || TID.mayStore()))
return false;
// Scan for the memory address operand.
@@ -119,8 +119,9 @@ bool MemSelOpt::processInstruction(MachineInstr *MI) {
for (unsigned i = 0; i < NumOperands; i++) {
MachineOperand Op = MI->getOperand(i);
if (Op.getType() == MachineOperand::MO_GlobalAddress ||
- Op.getType() == MachineOperand::MO_ExternalSymbol) {
- // We found one mem operand. Next one should be BS.
+ Op.getType() == MachineOperand::MO_ExternalSymbol ||
+ Op.getType() == MachineOperand::MO_MachineBasicBlock) {
+ // We found one mem operand. Next one may be BS.
MemOpPos = i;
break;
}
@@ -133,7 +134,8 @@ bool MemSelOpt::processInstruction(MachineInstr *MI) {
MachineOperand &Op = MI->getOperand(MemOpPos);
// If this is a pagesel material, handle it first.
- if (MI->getOpcode() == PIC16::CALL) {
+ if (MI->getOpcode() == PIC16::CALL ||
+ MI->getOpcode() == PIC16::br_uncond) {
DebugLoc dl = MI->getDebugLoc();
BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)).
addOperand(Op);
diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp
index d4f46a4..4304732 100644
--- a/lib/Target/PIC16/PIC16TargetMachine.cpp
+++ b/lib/Target/PIC16/PIC16TargetMachine.cpp
@@ -37,10 +37,8 @@ X("pic16", "PIC16 14-bit [experimental].");
static RegisterTarget<CooperTargetMachine>
Y("cooper", "PIC16 Cooper [experimental].");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializePIC16Target() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializePIC16Target() { }
// PIC16TargetMachine - Traditional PIC16 Machine.
PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS,
diff --git a/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt b/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt
index 1f80b17..236b264 100644
--- a/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt
@@ -3,3 +3,4 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMPowerPCAsmPrinter
PPCAsmPrinter.cpp
)
+add_dependencies(LLVMPowerPCAsmPrinter PowerPCCodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
index c7bfb6d..c5aa6ae 100644
--- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
@@ -24,6 +24,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
@@ -194,8 +195,6 @@ namespace {
std::string Name = Mang->getValueName(GV);
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
}
@@ -295,20 +294,17 @@ namespace {
/// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
class VISIBILITY_HIDDEN PPCLinuxAsmPrinter : public PPCAsmPrinter {
- DwarfWriter *DW;
- MachineModuleInfo *MMI;
public:
explicit PPCLinuxAsmPrinter(raw_ostream &O, PPCTargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : PPCAsmPrinter(O, TM, T, OL, V), DW(0), MMI(0) {}
+ : PPCAsmPrinter(O, TM, T, OL, V){}
virtual const char *getPassName() const {
return "Linux PPC Assembly Printer";
}
bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
bool doFinalization(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -324,14 +320,12 @@ namespace {
/// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac
/// OS X
class VISIBILITY_HIDDEN PPCDarwinAsmPrinter : public PPCAsmPrinter {
- DwarfWriter *DW;
- MachineModuleInfo *MMI;
raw_ostream &OS;
public:
explicit PPCDarwinAsmPrinter(raw_ostream &O, PPCTargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : PPCAsmPrinter(O, TM, T, OL, V), DW(0), MMI(0), OS(O) {}
+ : PPCAsmPrinter(O, TM, T, OL, V), OS(O) {}
virtual const char *getPassName() const {
return "Darwin PPC Assembly Printer";
@@ -403,17 +397,12 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
GVStubs.insert(Name);
printSuffixedName(Name, "$non_lazy_ptr");
}
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
}
O << Name;
printOffset(MO.getOffset());
-
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
@@ -644,15 +633,6 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
return false;
}
-bool PPCLinuxAsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- assert(MMI);
- SwitchToSection(TAI->getTextSection());
- return Result;
-}
-
/// PrintUnmangledNameSafely - Print out the printable characters in the name.
/// Don't print things like \\n or \\0.
static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
@@ -677,6 +657,8 @@ void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
printVisibility(name, GVar->getVisibility());
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -743,12 +725,6 @@ void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
}
O << '\n';
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
O << '\n';
}
@@ -759,11 +735,6 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
I != E; ++I)
printModuleLevelGV(I);
- // TODO
-
- // Emit initial debug information.
- DW->EndModule();
-
return AsmPrinter::doFinalization(M);
}
@@ -866,8 +837,6 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) {
O << "\t.machine " << CPUDirectives[Directive] << '\n';
bool Result = AsmPrinter::doInitialization(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
assert(MMI);
// Prime text sections so they are adjacent. This reduces the likelihood a
@@ -987,12 +956,6 @@ void PPCDarwinAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
}
O << '\n';
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
O << '\n';
}
@@ -1100,8 +1063,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
if (TAI->doesSupportExceptionHandling() && MMI) {
// Add the (possibly multiple) personalities to the set of global values.
// Only referenced functions get into the Personalities list.
- const std::vector<Function *>& Personalities = MMI->getPersonalities();
-
+ const std::vector<Function *> &Personalities = MMI->getPersonalities();
for (std::vector<Function *>::const_iterator I = Personalities.begin(),
E = Personalities.end(); I != E; ++I)
if (*I) GVStubs.insert("_" + (*I)->getName());
@@ -1139,10 +1101,6 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
}
}
-
- // Emit initial debug information.
- DW->EndModule();
-
// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
// implementation of multiple entry points). If this doesn't occur, the
@@ -1185,8 +1143,5 @@ namespace {
extern "C" int PowerPCAsmPrinterForceLink;
int PowerPCAsmPrinterForceLink = 0;
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializePowerPCAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializePowerPCAsmPrinter() { }
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index 3e89885..2f95d7e 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -35,10 +35,8 @@ X("ppc32", "PowerPC 32");
static RegisterTarget<PPC64TargetMachine>
Y("ppc64", "PowerPC 64");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializePowerPCTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializePowerPCTarget() { }
// No assembler printer by default
PPCTargetMachine::AsmPrinterCtorFn PPCTargetMachine::AsmPrinterCtor = 0;
diff --git a/lib/Target/Sparc/AsmPrinter/CMakeLists.txt b/lib/Target/Sparc/AsmPrinter/CMakeLists.txt
index de905a9..e3ca18e 100644
--- a/lib/Target/Sparc/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/Sparc/AsmPrinter/CMakeLists.txt
@@ -3,3 +3,4 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMSparcAsmPrinter
SparcAsmPrinter.cpp
)
+add_dependencies(LLVMSparcAsmPrinter SparcCodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
index 6a2fdca..cb23f62 100644
--- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
@@ -19,6 +19,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -46,11 +47,12 @@ namespace {
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
+ unsigned BBNumber;
public:
explicit SparcAsmPrinter(raw_ostream &O, TargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : AsmPrinter(O, TM, T, OL, V) {}
+ : AsmPrinter(O, TM, T, OL, V), BBNumber(0) {}
virtual const char *getPassName() const {
return "Sparc Assembly Printer";
@@ -101,7 +103,6 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// BBNumber is used here so that a given Printer will never give two
// BBs the same name. (If you have a better way, please let me know!)
- static unsigned BBNumber = 0;
O << "\n\n";
@@ -253,6 +254,8 @@ void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
O << "\n\n";
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
unsigned Size = TD->getTypeAllocSize(C->getType());
unsigned Align = TD->getPreferredAlignment(GVar);
@@ -362,8 +365,5 @@ namespace {
} Registrator;
}
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeSparcAsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeSparcAsmPrinter() { }
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index fd0f124..aef238d 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -25,10 +25,8 @@ static RegisterTarget<SparcTargetMachine> X("sparc", "SPARC");
SparcTargetMachine::AsmPrinterCtorFn SparcTargetMachine::AsmPrinterCtor = 0;
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeSparcTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeSparcTarget() { }
const TargetAsmInfo *SparcTargetMachine::createTargetAsmInfo() const {
// FIXME: Handle Solaris subtarget someday :)
diff --git a/lib/Target/X86/AsmPrinter/CMakeLists.txt b/lib/Target/X86/AsmPrinter/CMakeLists.txt
index 2079a9f..a28c826 100644
--- a/lib/Target/X86/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/X86/AsmPrinter/CMakeLists.txt
@@ -6,3 +6,4 @@ add_llvm_library(LLVMX86AsmPrinter
X86AsmPrinter.cpp
X86IntelAsmPrinter.cpp
)
+add_dependencies(LLVMX86AsmPrinter X86CodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
index 60ed4f0..e75cfc5 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
@@ -23,10 +23,13 @@
#include "llvm/CallingConv.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Type.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Support/CommandLine.h"
@@ -41,18 +44,26 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
static cl::opt<bool> NewAsmPrinter("experimental-asm-printer",
cl::Hidden);
-static std::string getPICLabelString(unsigned FnNum,
- const TargetAsmInfo *TAI,
- const X86Subtarget* Subtarget) {
- std::string label;
+//===----------------------------------------------------------------------===//
+// Primitive Helper Functions.
+//===----------------------------------------------------------------------===//
+
+void X86ATTAsmPrinter::PrintPICBaseSymbol() const {
if (Subtarget->isTargetDarwin())
- label = "\"L" + utostr_32(FnNum) + "$pb\"";
+ O << "\"L" << getFunctionNumber() << "$pb\"";
else if (Subtarget->isTargetELF())
- label = ".Lllvm$" + utostr_32(FnNum) + "." "$piclabel";
+ O << ".Lllvm$" << getFunctionNumber() << "." "$piclabel";
else
assert(0 && "Don't know how to print PIC label!\n");
+}
- return label;
+/// PrintUnmangledNameSafely - Print out the printable characters in the name.
+/// Don't print things like \\n or \\0.
+static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
+ for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
+ Name != E; ++Name)
+ if (isprint(*Name))
+ OS << *Name;
}
static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
@@ -89,15 +100,6 @@ static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
return Info;
}
-/// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \\n or \\0.
-static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
- for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
- Name != E; ++Name)
- if (isprint(*Name))
- OS << *Name;
-}
-
/// decorateName - Query FunctionInfoMap and use this information for various
/// name decoration.
void X86ATTAsmPrinter::decorateName(std::string &Name,
@@ -152,6 +154,8 @@ void X86ATTAsmPrinter::decorateName(std::string &Name,
}
}
+
+
void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
const Function *F = MF.getFunction();
@@ -159,9 +163,12 @@ void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
SwitchToSection(TAI->SectionForGlobal(F));
+ // FIXME: A function's alignment should be part of MachineFunction. There
+ // shouldn't be a policy decision here.
unsigned FnAlign = 4;
if (F->hasFnAttr(Attribute::OptimizeForSize))
FnAlign = 1;
+
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
@@ -283,13 +290,8 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
return false;
}
-static inline bool shouldPrintGOT(TargetMachine &TM, const X86Subtarget* ST) {
- return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_;
-}
-
static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) {
- return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ &&
- (ST->isPICStyleRIPRel() || ST->isPICStyleGOT());
+ return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_;
}
static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) {
@@ -324,6 +326,8 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
}
if (shouldPrintStub(TM, Subtarget)) {
+ // DARWIN/X86-32 in != static mode.
+
// Link-once, declaration, or Weakly-linked global variables need
// non-lazily-resolved stubs
if (GV->isDeclaration() || GV->isWeakForLinker()) {
@@ -354,9 +358,8 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
O << Name;
}
} else {
- if (GV->hasDLLImportLinkage()) {
+ if (GV->hasDLLImportLinkage())
O << "__imp_";
- }
O << Name;
if (shouldPrintPLT(TM, Subtarget)) {
@@ -370,9 +373,6 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
FnStubs.insert(Name);
}
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
printOffset(MO.getOffset());
if (needCloseParen)
@@ -386,7 +386,9 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
Name += MO.getSymbolName();
// Print function stub suffix unless it's Mac OS X 10.5 and up.
if (shouldPrintStub(TM, Subtarget) &&
+ // DARWIN/X86-32 in != static mode.
!(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
+
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
return;
@@ -401,23 +403,15 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
O << Name;
- if (shouldPrintPLT(TM, Subtarget)) {
- std::string GOTName(TAI->getGlobalPrefix());
- GOTName+="_GLOBAL_OFFSET_TABLE_";
- if (Name == GOTName)
- // HACK! Emit extra offset to PC during printing GOT offset to
- // compensate for the size of popl instruction. The resulting code
- // should look like:
- // call .piclabel
- // piclabel:
- // popl %some_register
- // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
- O << " + [.-"
- << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
-
- O << "@PLT";
+ if (MO.getTargetFlags() == X86II::MO_GOT_ABSOLUTE_ADDRESS) {
+ O << " + [.-";
+ PrintPICBaseSymbol();
+ O << ']';
}
+ if (shouldPrintPLT(TM, Subtarget))
+ O << "@PLT";
+
if (needCloseParen)
O << ')';
@@ -427,9 +421,10 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
}
void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier, bool NotRIPRel) {
+ const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
+ default: assert(0 && "unknown operand type!");
case MachineOperand::MO_Register: {
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
"Virtual registers should not make it this far!");
@@ -456,18 +451,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
if (!isMemOp) O << '$';
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
<< MO.getIndex();
-
- if (TM.getRelocationModel() == Reloc::PIC_) {
- if (Subtarget->isPICStyleStub())
- O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << "$pb\"";
- else if (Subtarget->isPICStyleGOT())
- O << "@GOTOFF";
- }
-
- if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
- O << "(%rip)";
- return;
+ break;
}
case MachineOperand::MO_ConstantPoolIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
@@ -475,38 +459,17 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
<< MO.getIndex();
- if (TM.getRelocationModel() == Reloc::PIC_) {
- if (Subtarget->isPICStyleStub())
- O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << "$pb\"";
- else if (Subtarget->isPICStyleGOT())
- O << "@GOTOFF";
- }
-
printOffset(MO.getOffset());
-
- if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
- O << "(%rip)";
- return;
+ break;
}
case MachineOperand::MO_GlobalAddress: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- bool needCloseParen = false;
const GlobalValue *GV = MO.getGlobal();
- const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
- if (!GVar) {
- // If GV is an alias then use the aliasee for determining
- // thread-localness.
- if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GVar =dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
- }
-
- bool isThreadLocal = GVar && GVar->isThreadLocal();
-
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
+ bool needCloseParen = false;
if (!isMemOp)
O << '$';
else if (Name[0] == '$') {
@@ -517,6 +480,8 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
}
if (shouldPrintStub(TM, Subtarget)) {
+ // DARWIN/X86-32 in != static mode.
+
// Link-once, declaration, or Weakly-linked global variables need
// non-lazily-resolved stubs
if (GV->isDeclaration() || GV->isWeakForLinker()) {
@@ -539,118 +504,59 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
O << Name;
}
- if (TM.getRelocationModel() == Reloc::PIC_)
- O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ O << '-';
+ PrintPICBaseSymbol();
+ }
} else {
if (GV->hasDLLImportLinkage())
O << "__imp_";
O << Name;
}
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
printOffset(MO.getOffset());
if (needCloseParen)
O << ')';
- bool isRIPRelative = false;
- if (isThreadLocal) {
- TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
- switch (model) {
- case TLSModel::GeneralDynamic:
- O << "@TLSGD";
- break;
- case TLSModel::LocalDynamic:
- // O << "@TLSLD"; // local dynamic not implemented
- O << "@TLSGD";
- break;
- case TLSModel::InitialExec:
- if (Subtarget->is64Bit()) {
- assert (!NotRIPRel);
- O << "@GOTTPOFF";
- isRIPRelative = true;
- } else {
- O << "@INDNTPOFF";
- }
- break;
- case TLSModel::LocalExec:
- if (Subtarget->is64Bit())
- O << "@TPOFF";
- else
- O << "@NTPOFF";
- break;
- default:
- assert (0 && "Unknown TLS model");
- }
- } else if (isMemOp) {
- if (shouldPrintGOT(TM, Subtarget)) {
- if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
- O << "@GOT";
- else
- O << "@GOTOFF";
- } else if (Subtarget->isPICStyleRIPRel() &&
- !NotRIPRel) {
- if (TM.getRelocationModel() != Reloc::Static) {
- if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
- O << "@GOTPCREL";
- }
-
- isRIPRelative = true;
- }
- }
-
- // Use rip when possible to reduce code size, except when
- // index or base register are also part of the address. e.g.
- // foo(%rip)(%rcx,%rax,4) is not legal.
- if (isRIPRelative)
- O << "(%rip)";
-
- return;
+ break;
}
- case MachineOperand::MO_ExternalSymbol: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- bool needCloseParen = false;
- std::string Name(TAI->getGlobalPrefix());
- Name += MO.getSymbolName();
-
- // Print function stub suffix unless it's Mac OS X 10.5 and up.
- if (!isMemOp)
- O << '$';
- else if (Name[0] == '$') {
- // The name begins with a dollar-sign. In order to avoid having it look
- // like an integer immediate to the assembler, enclose it in parens.
- O << '(';
- needCloseParen = true;
- }
-
- O << Name;
-
- if (shouldPrintPLT(TM, Subtarget)) {
- std::string GOTName(TAI->getGlobalPrefix());
- GOTName+="_GLOBAL_OFFSET_TABLE_";
- if (Name == GOTName)
- // HACK! Emit extra offset to PC during printing GOT offset to
- // compensate for the size of popl instruction. The resulting code
- // should look like:
- // call .piclabel
- // piclabel:
- // popl %some_register
- // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
- O << " + [.-"
- << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
- }
-
- if (needCloseParen)
- O << ')';
-
- if (Subtarget->isPICStyleRIPRel())
- O << "(%rip)";
- return;
+ case MachineOperand::MO_ExternalSymbol:
+ /// NOTE: MO_ExternalSymbol in a non-pcrel_imm context is *only* generated
+ /// by _GLOBAL_OFFSET_TABLE_ on X86-32. All others are call operands, which
+ /// are pcrel_imm's.
+ assert(!Subtarget->is64Bit() && !Subtarget->isPICStyleRIPRel());
+ // These are never used as memory operands.
+ assert(!(Modifier && !strcmp(Modifier, "mem")));
+
+ O << '$';
+ O << TAI->getGlobalPrefix();
+ O << MO.getSymbolName();
+ break;
}
+
+ switch (MO.getTargetFlags()) {
default:
- O << "<unknown operand type>"; return;
+ assert(0 && "Unknown target flag on GV operand");
+ case X86II::MO_NO_FLAG:
+ break;
+ case X86II::MO_GOT_ABSOLUTE_ADDRESS:
+ O << " + [.-";
+ PrintPICBaseSymbol();
+ O << ']';
+ break;
+ case X86II::MO_PIC_BASE_OFFSET:
+ O << '-';
+ PrintPICBaseSymbol();
+ break;
+ case X86II::MO_TLSGD: O << "@TLSGD"; break;
+ case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
+ case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
+ case X86II::MO_TPOFF: O << "@TPOFF"; break;
+ case X86II::MO_NTPOFF: O << "@NTPOFF"; break;
+ case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break;
+ case X86II::MO_GOT: O << "@GOT"; break;
+ case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
}
}
@@ -670,25 +576,24 @@ void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
}
void X86ATTAsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier,
- bool NotRIPRel) {
+ const char *Modifier) {
MachineOperand BaseReg = MI->getOperand(Op);
MachineOperand IndexReg = MI->getOperand(Op+2);
const MachineOperand &DispSpec = MI->getOperand(Op+3);
- NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
if (DispSpec.isGlobal() ||
DispSpec.isCPI() ||
DispSpec.isJTI() ||
DispSpec.isSymbol()) {
- printOperand(MI, Op+3, "mem", NotRIPRel);
+ printOperand(MI, Op+3, "mem");
} else {
int DispVal = DispSpec.getImm();
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
O << DispVal;
}
- if (IndexReg.getReg() || BaseReg.getReg()) {
+ if ((IndexReg.getReg() || BaseReg.getReg()) &&
+ (Modifier == 0 || strcmp(Modifier, "no-rip"))) {
unsigned ScaleVal = MI->getOperand(Op+1).getImm();
unsigned BaseRegOperand = 0, IndexRegOperand = 2;
@@ -716,14 +621,14 @@ void X86ATTAsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
}
void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier, bool NotRIPRel){
+ const char *Modifier) {
assert(isMem(MI, Op) && "Invalid memory reference!");
MachineOperand Segment = MI->getOperand(Op+4);
if (Segment.getReg()) {
printOperand(MI, Op+4, Modifier);
O << ':';
}
- printLeaMemReference(MI, Op, Modifier, NotRIPRel);
+ printLeaMemReference(MI, Op, Modifier);
}
void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
@@ -741,13 +646,19 @@ void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
if (Subtarget->isPICStyleRIPRel())
O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << uid << '\n';
- else
- O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << '\n';
+ else {
+ O << '-';
+ PrintPICBaseSymbol();
+ O << '\n';
+ }
}
+
void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
- std::string label = getPICLabelString(getFunctionNumber(), TAI, Subtarget);
- O << label << '\n' << label << ':';
+ PrintPICBaseSymbol();
+ O << '\n';
+ PrintPICBaseSymbol();
+ O << ':';
}
@@ -810,7 +721,7 @@ bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'c': // Don't print "$" before a global var name or constant.
- printOperand(MI, OpNo, "mem", /*NotRIPRel=*/true);
+ printOperand(MI, OpNo, "mem");
return false;
case 'b': // Print QImode register
case 'h': // Print QImode high register
@@ -823,8 +734,19 @@ bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
return false;
case 'P': // Don't print @PLT, but do print as memory.
- printOperand(MI, OpNo, "mem", /*NotRIPRel=*/true);
+ printOperand(MI, OpNo, "mem");
return false;
+
+ case 'n': { // Negate the immediate or print a '-' before the operand.
+ // Note: this is a temporary solution. It should be handled target
+ // independently as part of the 'MC' work.
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ if (MO.isImm()) {
+ O << -MO.getImm();
+ return false;
+ }
+ O << '-';
+ }
}
}
@@ -849,7 +771,7 @@ bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
// These only apply to registers, ignore on mem.
break;
case 'P': // Don't print @PLT, but do print as memory.
- printMemReference(MI, OpNo, "mem", /*NotRIPRel=*/true);
+ printMemReference(MI, OpNo, "no-rip");
return false;
}
}
@@ -931,8 +853,13 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
/// doInitialization
bool X86ATTAsmPrinter::doInitialization(Module &M) {
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+ if (NewAsmPrinter) {
+ Context = new MCContext();
+ // FIXME: Send this to "O" instead of outs(). For now, we force it to
+ // stdout to make it easy to compare.
+ Streamer = createAsmStreamer(*Context, outs());
+ }
+
return AsmPrinter::doInitialization(M);
}
@@ -956,6 +883,8 @@ void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
@@ -1068,25 +997,6 @@ void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
EmitGlobalConstant(C);
}
-/// printGVStub - Print stub for a global value.
-///
-void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) {
- printSuffixedName(GV, "$non_lazy_ptr", Prefix);
- O << ":\n\t.indirect_symbol ";
- if (Prefix) O << Prefix;
- O << GV << "\n\t.long\t0\n";
-}
-
-/// printHiddenGVStub - Print stub for a hidden global value.
-///
-void X86ATTAsmPrinter::printHiddenGVStub(const char *GV, const char *Prefix) {
- EmitAlignment(2);
- printSuffixedName(GV, "$non_lazy_ptr", Prefix);
- if (Prefix) O << Prefix;
- O << ":\n" << TAI->getData32bitsDirective() << GV << '\n';
-}
-
-
bool X86ATTAsmPrinter::doFinalization(Module &M) {
// Print out module-level global variables here.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
@@ -1095,100 +1005,62 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) {
if (I->hasDLLExportLinkage())
DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),""));
-
- // If the global is a extern weak symbol, remember to emit the weak
- // reference!
- // FIXME: This is rather hacky, since we'll emit references to ALL weak
- // stuff, not used. But currently it's the only way to deal with extern weak
- // initializers hidden deep inside constant expressions.
- if (I->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(I);
- }
-
- for (Module::const_iterator I = M.begin(), E = M.end();
- I != E; ++I) {
- // If the global is a extern weak symbol, remember to emit the weak
- // reference!
- // FIXME: This is rather hacky, since we'll emit references to ALL weak
- // stuff, not used. But currently it's the only way to deal with extern weak
- // initializers hidden deep inside constant expressions.
- if (I->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(I);
}
- // Output linker support code for dllexported globals
- if (!DLLExportedGVs.empty())
- SwitchToDataSection(".section .drectve");
-
- for (StringSet<>::iterator i = DLLExportedGVs.begin(),
- e = DLLExportedGVs.end();
- i != e; ++i)
- O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n";
-
- if (!DLLExportedFns.empty()) {
- SwitchToDataSection(".section .drectve");
- }
-
- for (StringSet<>::iterator i = DLLExportedFns.begin(),
- e = DLLExportedFns.end();
- i != e; ++i)
- O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n";
-
if (Subtarget->isTargetDarwin()) {
SwitchToDataSection("");
-
- // Output stubs for dynamically-linked functions
- for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
- i != e; ++i) {
- SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs,"
- "self_modifying_code+pure_instructions,5", 0);
- const char *p = i->getKeyData();
- printSuffixedName(p, "$stub");
- O << ":\n"
- "\t.indirect_symbol " << p << "\n"
- "\thlt ; hlt ; hlt ; hlt ; hlt\n";
- }
-
- O << '\n';
-
- // Print global value stubs.
- bool InStubSection = false;
+
+ // Add the (possibly multiple) personalities to the set of global value
+ // stubs. Only referenced functions get into the Personalities list.
if (TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) {
- // Add the (possibly multiple) personalities to the set of global values.
- // Only referenced functions get into the Personalities list.
- const std::vector<Function *>& Personalities = MMI->getPersonalities();
- for (std::vector<Function *>::const_iterator I = Personalities.begin(),
- E = Personalities.end(); I != E; ++I) {
- if (!*I)
+ const std::vector<Function*> &Personalities = MMI->getPersonalities();
+ for (unsigned i = 0, e = Personalities.size(); i != e; ++i) {
+ if (Personalities[i] == 0)
continue;
- if (!InStubSection) {
- SwitchToDataSection(
- "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers");
- InStubSection = true;
- }
- printGVStub((*I)->getNameStart(), "_");
+ std::string Name = Mang->getValueName(Personalities[i]);
+ decorateName(Name, Personalities[i]);
+ GVStubs.insert(Name);
}
}
+ // Output stubs for dynamically-linked functions
+ if (!FnStubs.empty()) {
+ for (StringSet<>::iterator I = FnStubs.begin(), E = FnStubs.end();
+ I != E; ++I) {
+ SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs,"
+ "self_modifying_code+pure_instructions,5", 0);
+ const char *Name = I->getKeyData();
+ printSuffixedName(Name, "$stub");
+ O << ":\n"
+ "\t.indirect_symbol " << Name << "\n"
+ "\thlt ; hlt ; hlt ; hlt ; hlt\n";
+ }
+ O << '\n';
+ }
+
// Output stubs for external and common global variables.
- if (!InStubSection && !GVStubs.empty())
+ if (!GVStubs.empty()) {
SwitchToDataSection(
"\t.section __IMPORT,__pointers,non_lazy_symbol_pointers");
- for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end();
- i != e; ++i)
- printGVStub(i->getKeyData());
+ for (StringSet<>::iterator I = GVStubs.begin(), E = GVStubs.end();
+ I != E; ++I) {
+ const char *Name = I->getKeyData();
+ printSuffixedName(Name, "$non_lazy_ptr");
+ O << ":\n\t.indirect_symbol " << Name << "\n\t.long\t0\n";
+ }
+ }
if (!HiddenGVStubs.empty()) {
SwitchToSection(TAI->getDataSection());
- for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end();
- i != e; ++i)
- printHiddenGVStub(i->getKeyData());
+ EmitAlignment(2);
+ for (StringSet<>::iterator I = HiddenGVStubs.begin(),
+ E = HiddenGVStubs.end(); I != E; ++I) {
+ const char *Name = I->getKeyData();
+ printSuffixedName(Name, "$non_lazy_ptr");
+ O << ":\n" << TAI->getData32bitsDirective() << Name << '\n';
+ }
}
- // Emit final debug information.
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW->EndModule();
-
// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
// implementation of multiple entry points). If this doesn't occur, the
@@ -1204,17 +1076,40 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) {
<< ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
<< ";\t.endef\n";
}
-
- // Emit final debug information.
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW->EndModule();
- } else if (Subtarget->isTargetELF()) {
- // Emit final debug information.
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW->EndModule();
}
-
- return AsmPrinter::doFinalization(M);
+
+
+ // Output linker support code for dllexported globals on windows.
+ if (!DLLExportedGVs.empty()) {
+ SwitchToDataSection(".section .drectve");
+
+ for (StringSet<>::iterator i = DLLExportedGVs.begin(),
+ e = DLLExportedGVs.end(); i != e; ++i)
+ O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n";
+ }
+
+ if (!DLLExportedFns.empty()) {
+ SwitchToDataSection(".section .drectve");
+
+ for (StringSet<>::iterator i = DLLExportedFns.begin(),
+ e = DLLExportedFns.end();
+ i != e; ++i)
+ O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n";
+ }
+
+ // Do common shutdown.
+ bool Changed = AsmPrinter::doFinalization(M);
+
+ if (NewAsmPrinter) {
+ Streamer->Finish();
+
+ delete Streamer;
+ delete Context;
+ Streamer = 0;
+ Context = 0;
+ }
+
+ return Changed;
}
// Include the auto-generated portion of the assembly writer.
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h
index 68a6bc8..bd96115 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h
+++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h
@@ -27,17 +27,23 @@
namespace llvm {
class MachineJumpTableInfo;
+class MCContext;
class MCInst;
+class MCStreamer;
class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
- MachineModuleInfo *MMI;
const X86Subtarget *Subtarget;
+
+ MCContext *Context;
+ MCStreamer *Streamer;
public:
explicit X86ATTAsmPrinter(raw_ostream &O, X86TargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : AsmPrinter(O, TM, T, OL, V), MMI(0) {
+ : AsmPrinter(O, TM, T, OL, V) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
+ Context = 0;
+ Streamer = 0;
}
virtual const char *getPassName() const {
@@ -69,7 +75,7 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
bool printInstruction(const MCInst *MI);
void printOperand(const MCInst *MI, unsigned OpNo,
- const char *Modifier = 0, bool NotRIPRel = false);
+ const char *Modifier = 0);
void printMemReference(const MCInst *MI, unsigned Op);
void printLeaMemReference(const MCInst *MI, unsigned Op);
void printSSECC(const MCInst *MI, unsigned Op);
@@ -117,7 +123,7 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
// These methods are used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier = 0, bool NotRIPRel = false);
+ const char *Modifier = 0);
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
@@ -165,9 +171,9 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
void printMachineInstruction(const MachineInstr *MI);
void printSSECC(const MachineInstr *MI, unsigned Op);
void printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL, bool NotRIPRel = false);
+ const char *Modifier=NULL);
void printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL, bool NotRIPRel = false);
+ const char *Modifier=NULL);
void printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const;
void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
@@ -181,9 +187,8 @@ class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
void printPICLabel(const MachineInstr *MI, unsigned Op);
void printModuleLevelGV(const GlobalVariable* GVar);
- void printGVStub(const char *GV, const char *Prefix = NULL);
- void printHiddenGVStub(const char *GV, const char *Prefix = NULL);
-
+ void PrintPICBaseSymbol() const;
+
bool runOnMachineFunction(MachineFunction &F);
void emitFunctionHeader(const MachineFunction &MF);
diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
index 9d50edc..fa0ee75 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp
@@ -65,7 +65,7 @@ void X86ATTAsmPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
- const char *Modifier, bool NotRIPRel) {
+ const char *Modifier) {
assert(Modifier == 0 && "Modifiers should not be used");
const MCOperand &Op = MI->getOperand(OpNo);
@@ -93,13 +93,11 @@ void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
}
void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
- bool NotRIPRel = false;
const MCOperand &BaseReg = MI->getOperand(Op);
const MCOperand &IndexReg = MI->getOperand(Op+2);
const MCOperand &DispSpec = MI->getOperand(Op+3);
- NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
if (DispSpec.isImm()) {
int64_t DispVal = DispSpec.getImm();
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
@@ -108,7 +106,7 @@ void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
abort();
//assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
// DispSpec.isJTI() || DispSpec.isSymbol());
- //printOperand(MI, Op+3, "mem", NotRIPRel);
+ //printOperand(MI, Op+3, "mem");
}
if (IndexReg.getReg() || BaseReg.getReg()) {
diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
index a39203b..d1623d6 100644
--- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
@@ -47,8 +47,5 @@ namespace {
extern "C" int X86AsmPrinterForceLink;
int X86AsmPrinterForceLink = 0;
-// Force static initialization when called from
-// llvm/InitializeAllAsmPrinters.h
-namespace llvm {
- void InitializeX86AsmPrinter() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeX86AsmPrinter() { }
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index 8df138d..4d26364 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -55,6 +55,13 @@ def FeatureSlowBTMem : SubtargetFeature<"slow-bt-mem", "IsBTMemSlow", "true",
def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true",
"Support SSE 4a instructions">;
+def FeatureAVX : SubtargetFeature<"avx", "HasAVX", "true",
+ "Enable AVX instructions">;
+def FeatureFMA3 : SubtargetFeature<"fma3", "HasFMA3", "true",
+ "Enable three-operand fused multiple-add">;
+def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true",
+ "Enable four-operand fused multiple-add">;
+
//===----------------------------------------------------------------------===//
// X86 processors supported.
//===----------------------------------------------------------------------===//
@@ -82,6 +89,9 @@ def : Proc<"core2", [FeatureSSSE3, Feature64Bit, FeatureSlowBTMem]>;
def : Proc<"penryn", [FeatureSSE41, Feature64Bit, FeatureSlowBTMem]>;
def : Proc<"atom", [FeatureSSE3, Feature64Bit, FeatureSlowBTMem]>;
def : Proc<"corei7", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem]>;
+def : Proc<"nehalem", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem]>;
+// Sandy Bridge does not have FMA
+def : Proc<"sandybridge", [FeatureSSE42, FeatureAVX, Feature64Bit]>;
def : Proc<"k6", [FeatureMMX]>;
def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>;
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp
index e988a5c..d5846a0 100644
--- a/lib/Target/X86/X86CodeEmitter.cpp
+++ b/lib/Target/X86/X86CodeEmitter.cpp
@@ -301,7 +301,7 @@ bool Emitter<CodeEmitter>::gvNeedsNonLazyPtr(const GlobalValue *GV) {
template<class CodeEmitter>
void Emitter<CodeEmitter>::emitDisplacementField(const MachineOperand *RelocOp,
- int DispVal, intptr_t PCAdj) {
+ int DispVal, intptr_t PCAdj) {
// If this is a simple integer displacement that doesn't require a relocation,
// emit it now.
if (!RelocOp) {
@@ -371,8 +371,10 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
// Is a SIB byte needed?
if ((!Is64BitMode || DispForReloc || BaseReg != 0) &&
IndexReg.getReg() == 0 &&
- (BaseReg == 0 || getX86RegNum(BaseReg) != N86::ESP)) {
- if (BaseReg == 0) { // Just a displacement?
+ (BaseReg == 0 || BaseReg == X86::RIP ||
+ getX86RegNum(BaseReg) != N86::ESP)) {
+ if (BaseReg == 0 ||
+ BaseReg == X86::RIP) { // Just a displacement?
// Emit special case [disp32] encoding
MCE.emitByte(ModRMByte(0, RegOpcodeField, 5));
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 2bcfd76..8a21b35 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -396,8 +396,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
// Constant-offset addressing.
Disp += CI->getSExtValue() * S;
} else if (IndexReg == 0 &&
- (!AM.GV ||
- !getTargetMachine()->symbolicAddressesAreRIPRel()) &&
+ (!AM.GV || !Subtarget->isPICStyleRIPRel()) &&
(S == 1 || S == 2 || S == 4 || S == 8)) {
// Scaled-index addressing.
Scale = S;
@@ -432,7 +431,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
return false;
// RIP-relative addresses can't have additional register operands.
- if (getTargetMachine()->symbolicAddressesAreRIPRel() &&
+ if (Subtarget->isPICStyleRIPRel() &&
(AM.Base.Reg != 0 || AM.IndexReg != 0))
return false;
@@ -443,6 +442,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
// Set up the basic address.
AM.GV = GV;
+
if (!isCall &&
TM.getRelocationModel() == Reloc::PIC_ &&
!Subtarget->is64Bit())
@@ -481,12 +481,16 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
// Prevent loading GV stub multiple times in same MBB.
LocalValueMap[V] = AM.Base.Reg;
+ } else if (Subtarget->isPICStyleRIPRel()) {
+ // Use rip-relative addressing if we can.
+ AM.Base.Reg = X86::RIP;
}
+
return true;
}
// If all else fails, try to materialize the value in a register.
- if (!AM.GV || !getTargetMachine()->symbolicAddressesAreRIPRel()) {
+ if (!AM.GV || !Subtarget->isPICStyleRIPRel()) {
if (AM.Base.Reg == 0) {
AM.Base.Reg = getRegForValue(V);
return AM.Base.Reg != 0;
@@ -1140,12 +1144,10 @@ bool X86FastISel::X86SelectCall(Instruction *I) {
return false;
unsigned CalleeOp = 0;
GlobalValue *GV = 0;
- if (CalleeAM.Base.Reg != 0) {
- assert(CalleeAM.GV == 0);
- CalleeOp = CalleeAM.Base.Reg;
- } else if (CalleeAM.GV != 0) {
- assert(CalleeAM.GV != 0);
+ if (CalleeAM.GV != 0) {
GV = CalleeAM.GV;
+ } else if (CalleeAM.Base.Reg != 0) {
+ CalleeOp = CalleeAM.Base.Reg;
} else
return false;
@@ -1493,15 +1495,22 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C) {
// x86-32 PIC requires a PIC base register for constant pools.
unsigned PICBase = 0;
- if (TM.getRelocationModel() == Reloc::PIC_ &&
- !Subtarget->is64Bit())
- PICBase = getInstrInfo()->getGlobalBaseReg(&MF);
+ unsigned char OpFlag = 0;
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ if (Subtarget->isPICStyleStub()) {
+ OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ PICBase = getInstrInfo()->getGlobalBaseReg(&MF);
+ } else if (Subtarget->isPICStyleGOT()) {
+ OpFlag = X86II::MO_GOTOFF;
+ PICBase = getInstrInfo()->getGlobalBaseReg(&MF);
+ }
+ }
// Create the load from the constant pool.
unsigned MCPOffset = MCP.getConstantPoolIndex(C, Align);
unsigned ResultReg = createResultReg(RC);
- addConstantPoolReference(BuildMI(MBB, DL, TII.get(Opc), ResultReg), MCPOffset,
- PICBase);
+ addConstantPoolReference(BuildMI(MBB, DL, TII.get(Opc), ResultReg),
+ MCPOffset, PICBase, OpFlag);
return ResultReg;
}
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 9cedafc..1336177 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -65,7 +65,6 @@ namespace {
int FrameIndex;
} Base;
- bool isRIPRel; // RIP as base?
unsigned Scale;
SDValue IndexReg;
int32_t Disp;
@@ -75,15 +74,35 @@ namespace {
const char *ES;
int JT;
unsigned Align; // CP alignment.
+ unsigned char SymbolFlags; // X86II::MO_*
X86ISelAddressMode()
- : BaseType(RegBase), isRIPRel(false), Scale(1), IndexReg(), Disp(0),
- Segment(), GV(0), CP(0), ES(0), JT(-1), Align(0) {
+ : BaseType(RegBase), Scale(1), IndexReg(), Disp(0),
+ Segment(), GV(0), CP(0), ES(0), JT(-1), Align(0), SymbolFlags(0) {
}
bool hasSymbolicDisplacement() const {
return GV != 0 || CP != 0 || ES != 0 || JT != -1;
}
+
+ bool hasBaseOrIndexReg() const {
+ return IndexReg.getNode() != 0 || Base.Reg.getNode() != 0;
+ }
+
+ /// isRIPRelative - Return true if this addressing mode is already RIP
+ /// relative.
+ bool isRIPRelative() const {
+ if (BaseType != RegBase) return false;
+ if (RegisterSDNode *RegNode =
+ dyn_cast_or_null<RegisterSDNode>(Base.Reg.getNode()))
+ return RegNode->getReg() == X86::RIP;
+ return false;
+ }
+
+ void setBaseReg(SDValue Reg) {
+ BaseType = RegBase;
+ Base.Reg = Reg;
+ }
void dump() {
cerr << "X86ISelAddressMode " << this << "\n";
@@ -91,7 +110,7 @@ namespace {
if (Base.Reg.getNode() != 0) Base.Reg.getNode()->dump();
else cerr << "nul";
cerr << " Base.FrameIndex " << Base.FrameIndex << "\n";
- cerr << "isRIPRel " << isRIPRel << " Scale" << Scale << "\n";
+ cerr << " Scale" << Scale << "\n";
cerr << "IndexReg ";
if (IndexReg.getNode() != 0) IndexReg.getNode()->dump();
else cerr << "nul";
@@ -200,14 +219,15 @@ namespace {
// These are 32-bit even in 64-bit mode since RIP relative offset
// is 32-bit.
if (AM.GV)
- Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp);
+ Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp,
+ AM.SymbolFlags);
else if (AM.CP)
Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32,
- AM.Align, AM.Disp);
+ AM.Align, AM.Disp, AM.SymbolFlags);
else if (AM.ES)
- Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32);
+ Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
else if (AM.JT != -1)
- Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32);
+ Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
else
Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
@@ -683,61 +703,80 @@ bool X86DAGToDAGISel::MatchLoad(SDValue N, X86ISelAddressMode &AM) {
return true;
}
+/// MatchWrapper - Try to match X86ISD::Wrapper and X86ISD::WrapperRIP nodes
+/// into an addressing mode. These wrap things that will resolve down into a
+/// symbol reference. If no match is possible, this returns true, otherwise it
+/// returns false.
bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) {
- bool SymbolicAddressesAreRIPRel =
- getTargetMachine().symbolicAddressesAreRIPRel();
- bool is64Bit = Subtarget->is64Bit();
- DOUT << "Wrapper: 64bit " << is64Bit;
- DOUT << " AM "; DEBUG(AM.dump()); DOUT << "\n";
-
- // Under X86-64 non-small code model, GV (and friends) are 64-bits.
- if (is64Bit && (TM.getCodeModel() != CodeModel::Small))
- return true;
-
- // Base and index reg must be 0 in order to use rip as base.
- bool canUsePICRel = !AM.Base.Reg.getNode() && !AM.IndexReg.getNode();
- if (is64Bit && !canUsePICRel && SymbolicAddressesAreRIPRel)
- return true;
-
+ // If the addressing mode already has a symbol as the displacement, we can
+ // never match another symbol.
if (AM.hasSymbolicDisplacement())
return true;
- // If value is available in a register both base and index components have
- // been picked, we can't fit the result available in the register in the
- // addressing mode. Duplicate GlobalAddress or ConstantPool as displacement.
SDValue N0 = N.getOperand(0);
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
- uint64_t Offset = G->getOffset();
- if (!is64Bit || isInt32(AM.Disp + Offset)) {
- GlobalValue *GV = G->getGlobal();
- bool isRIPRel = SymbolicAddressesAreRIPRel;
- if (N0.getOpcode() == llvm::ISD::TargetGlobalTLSAddress) {
- TLSModel::Model model =
- getTLSModel (GV, TM.getRelocationModel());
- if (is64Bit && model == TLSModel::InitialExec)
- isRIPRel = true;
- }
- AM.GV = GV;
- AM.Disp += Offset;
- AM.isRIPRel = isRIPRel;
- return false;
- }
- } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
- uint64_t Offset = CP->getOffset();
- if (!is64Bit || isInt32(AM.Disp + Offset)) {
+
+ // Handle X86-64 rip-relative addresses. We check this before checking direct
+ // folding because RIP is preferable to non-RIP accesses.
+ if (Subtarget->is64Bit() &&
+ // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
+ // they cannot be folded into immediate fields.
+ // FIXME: This can be improved for kernel and other models?
+ TM.getCodeModel() == CodeModel::Small &&
+
+ // Base and index reg must be 0 in order to use %rip as base and lowering
+ // must allow RIP.
+ !AM.hasBaseOrIndexReg() && N.getOpcode() == X86ISD::WrapperRIP) {
+
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
+ int64_t Offset = AM.Disp + G->getOffset();
+ if (!isInt32(Offset)) return true;
+ AM.GV = G->getGlobal();
+ AM.Disp = Offset;
+ AM.SymbolFlags = G->getTargetFlags();
+ } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
+ int64_t Offset = AM.Disp + CP->getOffset();
+ if (!isInt32(Offset)) return true;
AM.CP = CP->getConstVal();
AM.Align = CP->getAlignment();
- AM.Disp += Offset;
- AM.isRIPRel = SymbolicAddressesAreRIPRel;
- return false;
+ AM.Disp = Offset;
+ AM.SymbolFlags = CP->getTargetFlags();
+ } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
+ AM.ES = S->getSymbol();
+ AM.SymbolFlags = S->getTargetFlags();
+ } else {
+ JumpTableSDNode *J = cast<JumpTableSDNode>(N0);
+ AM.JT = J->getIndex();
+ AM.SymbolFlags = J->getTargetFlags();
}
- } else if (ExternalSymbolSDNode *S =dyn_cast<ExternalSymbolSDNode>(N0)) {
- AM.ES = S->getSymbol();
- AM.isRIPRel = SymbolicAddressesAreRIPRel;
+
+ if (N.getOpcode() == X86ISD::WrapperRIP)
+ AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
return false;
- } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
- AM.JT = J->getIndex();
- AM.isRIPRel = SymbolicAddressesAreRIPRel;
+ }
+
+ // Handle the case when globals fit in our immediate field: This is true for
+ // X86-32 always and X86-64 when in -static -mcmodel=small mode. In 64-bit
+ // mode, this results in a non-RIP-relative computation.
+ if (!Subtarget->is64Bit() ||
+ (TM.getCodeModel() == CodeModel::Small &&
+ TM.getRelocationModel() == Reloc::Static)) {
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
+ AM.GV = G->getGlobal();
+ AM.Disp += G->getOffset();
+ AM.SymbolFlags = G->getTargetFlags();
+ } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
+ AM.CP = CP->getConstVal();
+ AM.Align = CP->getAlignment();
+ AM.Disp += CP->getOffset();
+ AM.SymbolFlags = CP->getTargetFlags();
+ } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
+ AM.ES = S->getSymbol();
+ AM.SymbolFlags = S->getTargetFlags();
+ } else {
+ JumpTableSDNode *J = cast<JumpTableSDNode>(N0);
+ AM.JT = J->getIndex();
+ AM.SymbolFlags = J->getTargetFlags();
+ }
return false;
}
@@ -756,12 +795,19 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
if (Depth > 5)
return MatchAddressBase(N, AM);
+ // If this is already a %rip relative address, we can only merge immediates
+ // into it. Instead of handling this in every case, we handle it here.
// RIP relative addressing: %rip + 32-bit displacement!
- if (AM.isRIPRel) {
- if (!AM.ES && AM.JT != -1 && N.getOpcode() == ISD::Constant) {
- uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
- if (!is64Bit || isInt32(AM.Disp + Val)) {
- AM.Disp += Val;
+ if (AM.isRIPRelative()) {
+ // FIXME: JumpTable and ExternalSymbol address currently don't like
+ // displacements. It isn't very important, but this should be fixed for
+ // consistency.
+ if (!AM.ES && AM.JT != -1) return true;
+
+ if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) {
+ int64_t Val = AM.Disp + Cst->getSExtValue();
+ if (isInt32(Val)) {
+ AM.Disp = Val;
return false;
}
}
@@ -785,6 +831,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
break;
case X86ISD::Wrapper:
+ case X86ISD::WrapperRIP:
if (!MatchWrapper(N, AM))
return false;
break;
@@ -804,7 +851,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
break;
case ISD::SHL:
- if (AM.IndexReg.getNode() != 0 || AM.Scale != 1 || AM.isRIPRel)
+ if (AM.IndexReg.getNode() != 0 || AM.Scale != 1)
break;
if (ConstantSDNode
@@ -845,8 +892,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
// X*[3,5,9] -> X+X*[2,4,8]
if (AM.BaseType == X86ISelAddressMode::RegBase &&
AM.Base.Reg.getNode() == 0 &&
- AM.IndexReg.getNode() == 0 &&
- !AM.isRIPRel) {
+ AM.IndexReg.getNode() == 0) {
if (ConstantSDNode
*CN = dyn_cast<ConstantSDNode>(N.getNode()->getOperand(1)))
if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
@@ -895,7 +941,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
break;
}
// Test if the index field is free for use.
- if (AM.IndexReg.getNode() || AM.isRIPRel) {
+ if (AM.IndexReg.getNode() || AM.isRIPRelative()) {
AM = Backup;
break;
}
@@ -966,8 +1012,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
// the add.
if (AM.BaseType == X86ISelAddressMode::RegBase &&
!AM.Base.Reg.getNode() &&
- !AM.IndexReg.getNode() &&
- !AM.isRIPRel) {
+ !AM.IndexReg.getNode()) {
AM.Base.Reg = N.getNode()->getOperand(0);
AM.IndexReg = N.getNode()->getOperand(1);
AM.Scale = 1;
@@ -1006,9 +1051,6 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
// Scale must not be used already.
if (AM.IndexReg.getNode() != 0 || AM.Scale != 1) break;
- // Not when RIP is used as the base.
- if (AM.isRIPRel) break;
-
SDValue X = Shift.getOperand(0);
ConstantSDNode *C2 = dyn_cast<ConstantSDNode>(N.getOperand(1));
ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
@@ -1130,7 +1172,7 @@ bool X86DAGToDAGISel::MatchAddressBase(SDValue N, X86ISelAddressMode &AM) {
// Is the base register already occupied?
if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
// If so, check to see if the scale index register is set.
- if (AM.IndexReg.getNode() == 0 && !AM.isRIPRel) {
+ if (AM.IndexReg.getNode() == 0) {
AM.IndexReg = N;
AM.Scale = 1;
return false;
@@ -1157,7 +1199,7 @@ bool X86DAGToDAGISel::SelectAddr(SDValue Op, SDValue N, SDValue &Base,
if (AvoidDupAddrCompute && !N.hasOneUse()) {
unsigned Opcode = N.getOpcode();
if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex &&
- Opcode != X86ISD::Wrapper) {
+ Opcode != X86ISD::Wrapper && Opcode != X86ISD::WrapperRIP) {
// If we are able to fold N into addressing mode, then we'll allow it even
// if N has multiple uses. In general, addressing computation is used as
// addresses by all of its uses. But watch out for CopyToReg uses, that
@@ -1307,7 +1349,8 @@ bool X86DAGToDAGISel::SelectTLSADDRAddr(SDValue Op, SDValue N, SDValue &Base,
AM.GV = GA->getGlobal();
AM.Disp += GA->getOffset();
AM.Base.Reg = CurDAG->getRegister(0, N.getValueType());
-
+ AM.SymbolFlags = GA->getTargetFlags();
+
if (N.getValueType() == MVT::i32) {
AM.Scale = 1;
AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
@@ -1687,7 +1730,8 @@ SDNode *X86DAGToDAGISel::Select(SDValue N) {
// If N2 is not Wrapper(decriptor) then the llvm.declare is mangled
// somehow, just ignore it.
- if (N2.getOpcode() != X86ISD::Wrapper) {
+ if (N2.getOpcode() != X86ISD::Wrapper &&
+ N2.getOpcode() != X86ISD::WrapperRIP) {
ReplaceUses(N.getValue(0), Chain);
return NULL;
}
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 8d0ea66..9614e69 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -19,6 +19,7 @@
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/GlobalAlias.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
@@ -4311,21 +4312,102 @@ X86TargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
SDValue
X86TargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
- // FIXME there isn't really any debug info here, should come from the parent
- DebugLoc dl = CP->getDebugLoc();
+
+ // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
+ // global base reg.
+ unsigned char OpFlag = 0;
+ unsigned WrapperKind = X86ISD::Wrapper;
+ if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+ if (Subtarget->isPICStyleStub())
+ OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ else if (Subtarget->isPICStyleGOT())
+ OpFlag = X86II::MO_GOTOFF;
+ else if (Subtarget->isPICStyleRIPRel() &&
+ getTargetMachine().getCodeModel() == CodeModel::Small)
+ WrapperKind = X86ISD::WrapperRIP;
+ }
+
SDValue Result = DAG.getTargetConstantPool(CP->getConstVal(), getPointerTy(),
- CP->getAlignment());
- Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result);
+ CP->getAlignment(),
+ CP->getOffset(), OpFlag);
+ DebugLoc DL = CP->getDebugLoc();
+ Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result);
+ // With PIC, the address is actually $g + Offset.
+ if (OpFlag) {
+ Result = DAG.getNode(ISD::ADD, DL, getPointerTy(),
+ DAG.getNode(X86ISD::GlobalBaseReg,
+ DebugLoc::getUnknownLoc(), getPointerTy()),
+ Result);
+ }
+
+ return Result;
+}
+
+SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) {
+ JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+
+ // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
+ // global base reg.
+ unsigned char OpFlag = 0;
+ unsigned WrapperKind = X86ISD::Wrapper;
+ if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+ if (Subtarget->isPICStyleStub())
+ OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ else if (Subtarget->isPICStyleGOT())
+ OpFlag = X86II::MO_GOTOFF;
+ else if (Subtarget->isPICStyleRIPRel())
+ WrapperKind = X86ISD::WrapperRIP;
+ }
+
+ SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy(),
+ OpFlag);
+ DebugLoc DL = JT->getDebugLoc();
+ Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result);
+
+ // With PIC, the address is actually $g + Offset.
+ if (OpFlag) {
+ Result = DAG.getNode(ISD::ADD, DL, getPointerTy(),
+ DAG.getNode(X86ISD::GlobalBaseReg,
+ DebugLoc::getUnknownLoc(), getPointerTy()),
+ Result);
+ }
+
+ return Result;
+}
+
+SDValue
+X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) {
+ const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
+
+ // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
+ // global base reg.
+ unsigned char OpFlag = 0;
+ unsigned WrapperKind = X86ISD::Wrapper;
+ if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+ if (Subtarget->isPICStyleStub())
+ OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ else if (Subtarget->isPICStyleGOT())
+ OpFlag = X86II::MO_GOTOFF;
+ else if (Subtarget->isPICStyleRIPRel())
+ WrapperKind = X86ISD::WrapperRIP;
+ }
+
+ SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy(), OpFlag);
+
+ DebugLoc DL = Op.getDebugLoc();
+ Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result);
+
+
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
!Subtarget->isPICStyleRIPRel()) {
- Result = DAG.getNode(ISD::ADD, dl, getPointerTy(),
+ Result = DAG.getNode(ISD::ADD, DL, getPointerTy(),
DAG.getNode(X86ISD::GlobalBaseReg,
DebugLoc::getUnknownLoc(),
getPointerTy()),
Result);
}
-
+
return Result;
}
@@ -4343,9 +4425,29 @@ X86TargetLowering::LowerGlobalAddress(const GlobalValue *GV, DebugLoc dl,
if (!IsPic && !ExtraLoadRequired && isInt32(Offset)) {
Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset);
Offset = 0;
- } else
- Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0);
- Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result);
+ } else {
+ unsigned char OpFlags = 0;
+
+ if (Subtarget->isPICStyleRIPRel() &&
+ getTargetMachine().getRelocationModel() != Reloc::Static) {
+ if (ExtraLoadRequired)
+ OpFlags = X86II::MO_GOTPCREL;
+ } else if (Subtarget->isPICStyleGOT() &&
+ getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+ if (ExtraLoadRequired)
+ OpFlags = X86II::MO_GOT;
+ else
+ OpFlags = X86II::MO_GOTOFF;
+ }
+
+ Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0, OpFlags);
+ }
+
+ if (Subtarget->isPICStyleRIPRel() &&
+ getTargetMachine().getCodeModel() == CodeModel::Small)
+ Result = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Result);
+ else
+ Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result);
// With PIC, the address is actually $g + Offset.
if (IsPic && !Subtarget->isPICStyleRIPRel()) {
@@ -4381,12 +4483,14 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
static SDValue
GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
- SDValue *InFlag, const MVT PtrVT, unsigned ReturnReg) {
+ SDValue *InFlag, const MVT PtrVT, unsigned ReturnReg,
+ unsigned char OperandFlags) {
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
DebugLoc dl = GA->getDebugLoc();
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
GA->getValueType(0),
- GA->getOffset());
+ GA->getOffset(),
+ OperandFlags);
if (InFlag) {
SDValue Ops[] = { Chain, TGA, *InFlag };
Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3);
@@ -4410,14 +4514,15 @@ LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
PtrVT), InFlag);
InFlag = Chain.getValue(1);
- return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX);
+ return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX, X86II::MO_TLSGD);
}
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit
static SDValue
LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG,
const MVT PtrVT) {
- return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, X86::RAX);
+ return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT,
+ X86::RAX, X86II::MO_TLSGD);
}
// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or
@@ -4435,11 +4540,26 @@ static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
SDValue ThreadPointer = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Base,
NULL, 0);
+ unsigned char OperandFlags = 0;
+ // Most TLS accesses are not RIP relative, even on x86-64. One exception is
+ // initialexec.
+ unsigned WrapperKind = X86ISD::Wrapper;
+ if (model == TLSModel::LocalExec) {
+ OperandFlags = is64Bit ? X86II::MO_TPOFF : X86II::MO_NTPOFF;
+ } else if (is64Bit) {
+ assert(model == TLSModel::InitialExec);
+ OperandFlags = X86II::MO_GOTTPOFF;
+ WrapperKind = X86ISD::WrapperRIP;
+ } else {
+ assert(model == TLSModel::InitialExec);
+ OperandFlags = X86II::MO_INDNTPOFF;
+ }
+
// emit "addl x@ntpoff,%eax" (local exec) or "addl x@indntpoff,%eax" (initial
// exec)
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
- GA->getOffset());
- SDValue Offset = DAG.getNode(X86ISD::Wrapper, dl, PtrVT, TGA);
+ GA->getOffset(), OperandFlags);
+ SDValue Offset = DAG.getNode(WrapperKind, dl, PtrVT, TGA);
if (model == TLSModel::InitialExec)
Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Offset,
@@ -4457,72 +4577,33 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) {
assert(Subtarget->isTargetELF() &&
"TLS not implemented for non-ELF targets");
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
- GlobalValue *GV = GA->getGlobal();
- TLSModel::Model model =
- getTLSModel (GV, getTargetMachine().getRelocationModel());
- if (Subtarget->is64Bit()) {
- switch (model) {
- case TLSModel::GeneralDynamic:
- case TLSModel::LocalDynamic: // not implemented
+ const GlobalValue *GV = GA->getGlobal();
+
+ // If GV is an alias then use the aliasee for determining
+ // thread-localness.
+ if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
+ GV = GA->resolveAliasedGlobal(false);
+
+ TLSModel::Model model = getTLSModel(GV,
+ getTargetMachine().getRelocationModel());
+
+ switch (model) {
+ case TLSModel::GeneralDynamic:
+ case TLSModel::LocalDynamic: // not implemented
+ if (Subtarget->is64Bit())
return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy());
-
- case TLSModel::InitialExec:
- case TLSModel::LocalExec:
- return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, true);
- }
- } else {
- switch (model) {
- case TLSModel::GeneralDynamic:
- case TLSModel::LocalDynamic: // not implemented
- return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy());
-
- case TLSModel::InitialExec:
- case TLSModel::LocalExec:
- return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, false);
- }
+ return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy());
+
+ case TLSModel::InitialExec:
+ case TLSModel::LocalExec:
+ return LowerToTLSExecModel(GA, DAG, getPointerTy(), model,
+ Subtarget->is64Bit());
}
+
assert(0 && "Unreachable");
return SDValue();
}
-SDValue
-X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) {
- // FIXME there isn't really any debug info here
- DebugLoc dl = Op.getDebugLoc();
- const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
- SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy());
- Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result);
- // With PIC, the address is actually $g + Offset.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
- !Subtarget->isPICStyleRIPRel()) {
- Result = DAG.getNode(ISD::ADD, dl, getPointerTy(),
- DAG.getNode(X86ISD::GlobalBaseReg,
- DebugLoc::getUnknownLoc(),
- getPointerTy()),
- Result);
- }
-
- return Result;
-}
-
-SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) {
- JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
- // FIXME there isn't really any debug into here
- DebugLoc dl = JT->getDebugLoc();
- SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy());
- Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result);
- // With PIC, the address is actually $g + Offset.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
- !Subtarget->isPICStyleRIPRel()) {
- Result = DAG.getNode(ISD::ADD, dl, getPointerTy(),
- DAG.getNode(X86ISD::GlobalBaseReg,
- DebugLoc::getUnknownLoc(),
- getPointerTy()),
- Result);
- }
-
- return Result;
-}
/// LowerShift - Lower SRA_PARTS and friends, which return two i32 values and
/// take a 2 x i32 value to shift plus a shift amount.
@@ -6779,6 +6860,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::REP_MOVS: return "X86ISD::REP_MOVS";
case X86ISD::GlobalBaseReg: return "X86ISD::GlobalBaseReg";
case X86ISD::Wrapper: return "X86ISD::Wrapper";
+ case X86ISD::WrapperRIP: return "X86ISD::WrapperRIP";
case X86ISD::PEXTRB: return "X86ISD::PEXTRB";
case X86ISD::PEXTRW: return "X86ISD::PEXTRW";
case X86ISD::INSERTPS: return "X86ISD::INSERTPS";
diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td
index 063913f..472ba4c 100644
--- a/lib/Target/X86/X86Instr64bit.td
+++ b/lib/Target/X86/X86Instr64bit.td
@@ -45,7 +45,8 @@ def lea64_32mem : Operand<i32> {
// Complex Pattern Definitions.
//
def lea64addr : ComplexPattern<i64, 4, "SelectLEAAddr",
- [add, mul, X86mul_imm, shl, or, frameindex, X86Wrapper],
+ [add, mul, X86mul_imm, shl, or, frameindex, X86Wrapper,
+ X86WrapperRIP],
[]>;
def tls64addr : ComplexPattern<i64, 4, "SelectTLSADDRAddr",
@@ -1418,6 +1419,9 @@ def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
(MOV64ri texternalsym:$dst)>, Requires<[NotSmallCode]>;
+// If we have small model and -static mode, it is safe to store global addresses
+// directly as immediates. FIXME: This is really a hack, the 'imm' predicate
+// should handle this sort of thing.
def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst),
(MOV64mi32 addr:$dst, tconstpool:$src)>,
Requires<[SmallCode, IsStatic]>;
@@ -1431,6 +1435,23 @@ def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst),
(MOV64mi32 addr:$dst, texternalsym:$src)>,
Requires<[SmallCode, IsStatic]>;
+// If we have small model and -static mode, it is safe to store global addresses
+// directly as immediates. FIXME: This is really a hack, the 'imm' predicate
+// should handle this sort of thing.
+def : Pat<(store (i64 (X86WrapperRIP tconstpool:$src)), addr:$dst),
+ (MOV64mi32 addr:$dst, tconstpool:$src)>,
+ Requires<[SmallCode, IsStatic]>;
+def : Pat<(store (i64 (X86WrapperRIP tjumptable:$src)), addr:$dst),
+ (MOV64mi32 addr:$dst, tjumptable:$src)>,
+ Requires<[SmallCode, IsStatic]>;
+def : Pat<(store (i64 (X86WrapperRIP tglobaladdr:$src)), addr:$dst),
+ (MOV64mi32 addr:$dst, tglobaladdr:$src)>,
+ Requires<[SmallCode, IsStatic]>;
+def : Pat<(store (i64 (X86WrapperRIP texternalsym:$src)), addr:$dst),
+ (MOV64mi32 addr:$dst, texternalsym:$src)>,
+ Requires<[SmallCode, IsStatic]>;
+
+
// Calls
// Direct PC relative function call for small code model. 32-bit displacement
// sign extended to 64-bit.
diff --git a/lib/Target/X86/X86InstrBuilder.h b/lib/Target/X86/X86InstrBuilder.h
index 39504cd..b50dd65 100644
--- a/lib/Target/X86/X86InstrBuilder.h
+++ b/lib/Target/X86/X86InstrBuilder.h
@@ -157,10 +157,10 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
///
inline const MachineInstrBuilder &
addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
- unsigned GlobalBaseReg = 0) {
+ unsigned GlobalBaseReg, unsigned char OpFlags) {
//FIXME: factor this
return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0)
- .addConstantPoolIndex(CPI).addReg(0);
+ .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0);
}
} // End llvm namespace
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 8a9b7c9..21f71ec 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -18,6 +18,7 @@
#include "X86MachineFunctionInfo.h"
#include "X86Subtarget.h"
#include "X86TargetMachine.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -28,7 +29,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetAsmInfo.h"
-
using namespace llvm;
namespace {
@@ -781,6 +781,29 @@ static bool regIsPICBase(unsigned BaseReg, const MachineRegisterInfo &MRI) {
static inline bool isGVStub(GlobalValue *GV, X86TargetMachine &TM) {
return TM.getSubtarget<X86Subtarget>().GVRequiresExtraLoad(GV, TM, false);
}
+
+/// CanRematLoadWithDispOperand - Return true if a load with the specified
+/// operand is a candidate for remat: for this to be true we need to know that
+/// the load will always return the same value, even if moved.
+static bool CanRematLoadWithDispOperand(const MachineOperand &MO,
+ X86TargetMachine &TM) {
+ // Loads from constant pool entries can be remat'd.
+ if (MO.isCPI()) return true;
+
+ // We can remat globals in some cases.
+ if (MO.isGlobal()) {
+ // If this is a load of a stub, not of the global, we can remat it. This
+ // access will always return the address of the global.
+ if (isGVStub(MO.getGlobal(), TM))
+ return true;
+
+ // If the global itself is constant, we can remat the load.
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal()))
+ if (GV->isConstant())
+ return true;
+ }
+ return false;
+}
bool
X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI) const {
@@ -802,11 +825,9 @@ X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI) const {
if (MI->getOperand(1).isReg() &&
MI->getOperand(2).isImm() &&
MI->getOperand(3).isReg() && MI->getOperand(3).getReg() == 0 &&
- (MI->getOperand(4).isCPI() ||
- (MI->getOperand(4).isGlobal() &&
- isGVStub(MI->getOperand(4).getGlobal(), TM)))) {
+ CanRematLoadWithDispOperand(MI->getOperand(4), TM)) {
unsigned BaseReg = MI->getOperand(1).getReg();
- if (BaseReg == 0)
+ if (BaseReg == 0 || BaseReg == X86::RIP)
return true;
// Allow re-materialization of PIC load.
if (!ReMatPICStubLoad && MI->getOperand(4).isGlobal())
@@ -3190,9 +3211,8 @@ unsigned X86InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
bool IsPIC = (TM.getRelocationModel() == Reloc::PIC_);
bool Is64BitMode = TM.getSubtargetImpl()->is64Bit();
unsigned Size = GetInstSizeWithDesc(*MI, &Desc, IsPIC, Is64BitMode);
- if (Desc.getOpcode() == X86::MOVPC32r) {
+ if (Desc.getOpcode() == X86::MOVPC32r)
Size += GetInstSizeWithDesc(*MI, &get(X86::POP32r), IsPIC, Is64BitMode);
- }
return Size;
}
@@ -3220,17 +3240,17 @@ unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
const TargetInstrInfo *TII = TM.getInstrInfo();
// Operand of MovePCtoStack is completely ignored by asm printer. It's
// only used in JIT code emission as displacement to pc.
- BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC)
- .addImm(0);
+ BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
// If we're using vanilla 'GOT' PIC style, we should use relative addressing
- // not to pc, but to _GLOBAL_ADDRESS_TABLE_ external
+ // not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
if (TM.getRelocationModel() == Reloc::PIC_ &&
TM.getSubtarget<X86Subtarget>().isPICStyleGOT()) {
- GlobalBaseReg =
- RegInfo.createVirtualRegister(X86::GR32RegisterClass);
+ GlobalBaseReg = RegInfo.createVirtualRegister(X86::GR32RegisterClass);
+ // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], %some_register
BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
- .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_");
+ .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_", 0,
+ X86II::MO_GOT_ABSOLUTE_ADDRESS);
} else {
GlobalBaseReg = PC;
}
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index e09769e..83f0194 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -71,7 +71,86 @@ namespace X86 {
namespace X86II {
enum {
//===------------------------------------------------------------------===//
- // Instruction types. These are the standard/most common forms for X86
+ // X86 Specific MachineOperand flags.
+
+ MO_NO_FLAG = 0,
+
+ /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a
+ /// relocation of:
+ /// SYMBOL_LABEL + [. - PICBASELABEL]
+ MO_GOT_ABSOLUTE_ADDRESS = 1,
+
+ /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the
+ /// immediate should get the value of the symbol minus the PIC base label:
+ /// SYMBOL_LABEL - PICBASELABEL
+ MO_PIC_BASE_OFFSET = 2,
+
+ /// MO_GOT - On a symbol operand this indicates that the immediate is the
+ /// offset to the GOT entry for the symbol name from the base of the GOT.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOT
+ MO_GOT = 3,
+
+ /// MO_GOTOFF - On a symbol operand this indicates that the immediate is
+ /// the offset to the location of the symbol name from the base of the GOT.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOTOFF
+ MO_GOTOFF = 4,
+
+ /// MO_GOTPCREL - On a symbol operand this indicates that the immediate is
+ /// offset to the GOT entry for the symbol name from the current code
+ /// location.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOTPCREL
+ MO_GOTPCREL = 5,
+
+ /// MO_PLT - On a symbol operand this indicates that the immediate is
+ /// offset to the PLT entry of symbol name from the current code location.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @PLT
+ MO_PLT = 6,
+
+ /// MO_TLSGD - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @TLSGD
+ MO_TLSGD = 7,
+
+ /// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @GOTTPOFF
+ MO_GOTTPOFF = 8,
+
+ /// MO_INDNTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @INDNTPOFF
+ MO_INDNTPOFF = 9,
+
+ /// MO_TPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @TPOFF
+ MO_TPOFF = 10,
+
+ /// MO_NTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @NTPOFF
+ MO_NTPOFF = 11,
+
+ //===------------------------------------------------------------------===//
+ // Instruction encodings. These are the standard/most common forms for X86
// instructions.
//
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 2d8f55f..a6b0880 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -50,9 +50,9 @@ def SDTX86atomicBinary : SDTypeProfile<2, 3, [SDTCisInt<0>, SDTCisInt<1>,
SDTCisPtrTy<2>, SDTCisInt<3>,SDTCisInt<4>]>;
def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i16>]>;
-def SDT_X86CallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
-def SDT_X86CallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
- SDTCisVT<1, i32> ]>;
+def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
+def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
+ SDTCisVT<1, i32>]>;
def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
@@ -236,6 +236,10 @@ def HasSSE3 : Predicate<"Subtarget->hasSSE3()">;
def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">;
def HasSSE41 : Predicate<"Subtarget->hasSSE41()">;
def HasSSE42 : Predicate<"Subtarget->hasSSE42()">;
+def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">;
+def HasAVX : Predicate<"Subtarget->hasAVX()">;
+def HasFMA3 : Predicate<"Subtarget->hasFMA3()">;
+def HasFMA4 : Predicate<"Subtarget->hasFMA4()">;
def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">;
def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">;
def In32BitMode : Predicate<"!Subtarget->is64Bit()">;
diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td
index 43fadc2..b79a006 100644
--- a/lib/Target/X86/X86InstrMMX.td
+++ b/lib/Target/X86/X86InstrMMX.td
@@ -481,11 +481,11 @@ def MMX_PMOVMSKBrr : MMXI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR64:$src),
// Misc.
let Uses = [EDI] in
-def MMX_MASKMOVQ : MMXI<0xF7, MRMDestMem, (outs), (ins VR64:$src, VR64:$mask),
+def MMX_MASKMOVQ : MMXI<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask),
"maskmovq\t{$mask, $src|$src, $mask}",
[(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, EDI)]>;
let Uses = [RDI] in
-def MMX_MASKMOVQ64: MMXI64<0xF7, MRMDestMem, (outs), (ins VR64:$src, VR64:$mask),
+def MMX_MASKMOVQ64: MMXI64<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask),
"maskmovq\t{$mask, $src|$src, $mask}",
[(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, RDI)]>;
diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td
index d552cb3..996baa0 100644
--- a/lib/Target/X86/X86RegisterInfo.td
+++ b/lib/Target/X86/X86RegisterInfo.td
@@ -439,7 +439,7 @@ def GR32 : RegisterClass<"X86", [i32], 32,
def GR64 : RegisterClass<"X86", [i64], 64,
[RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
- RBX, R14, R15, R12, R13, RBP, RSP]> {
+ RBX, R14, R15, R12, R13, RBP, RSP, RIP]> {
let SubRegClassList = [GR8, GR8, GR16, GR32];
let MethodProtos = [{
iterator allocation_order_end(const MachineFunction &MF) const;
@@ -453,9 +453,9 @@ def GR64 : RegisterClass<"X86", [i64], 64,
if (!Subtarget.is64Bit())
return begin(); // None of these are allocatable in 32-bit.
if (RI->hasFP(MF)) // Does the function dedicate RBP to being a frame ptr?
- return end()-2; // If so, don't allocate RSP or RBP
+ return end()-3; // If so, don't allocate RIP, RSP or RBP
else
- return end()-1; // If not, just don't allocate RSP
+ return end()-2; // If not, just don't allocate RIP or RSP
}
}];
}
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index 56983ce..8506fa6 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -207,6 +207,10 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0;
bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0;
+
+ HasFMA3 = IsIntel && ((ECX >> 12) & 0x1);
+ HasAVX = ((ECX >> 28) & 0x1);
+
if (IsIntel || IsAMD) {
// Determine if bit test memory instructions are slow.
unsigned Family = 0;
@@ -217,6 +221,7 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
HasX86_64 = (EDX >> 29) & 0x1;
HasSSE4A = IsAMD && ((ECX >> 6) & 0x1);
+ HasFMA4 = IsAMD && ((ECX >> 16) & 0x1);
}
}
@@ -342,6 +347,10 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
, X86SSELevel(NoMMXSSE)
, X863DNowLevel(NoThreeDNow)
, HasX86_64(false)
+ , HasSSE4A(false)
+ , HasAVX(false)
+ , HasFMA3(false)
+ , HasFMA4(false)
, IsBTMemSlow(false)
, DarwinVers(0)
, IsLinux(false)
diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
index 694b0eb..f4f6cce 100644
--- a/lib/Target/X86/X86Subtarget.h
+++ b/lib/Target/X86/X86Subtarget.h
@@ -64,12 +64,21 @@ protected:
///
bool HasX86_64;
- /// IsBTMemSlow - True if BT (bit test) of memory instructions are slow.
- bool IsBTMemSlow;
-
/// HasSSE4A - True if the processor supports SSE4A instructions.
bool HasSSE4A;
+ /// HasAVX - Target has AVX instructions
+ bool HasAVX;
+
+ /// HasFMA3 - Target has 3-operand fused multiply-add
+ bool HasFMA3;
+
+ /// HasFMA4 - Target has 4-operand fused multiply-add
+ bool HasFMA4;
+
+ /// IsBTMemSlow - True if BT (bit test) of memory instructions are slow.
+ bool IsBTMemSlow;
+
/// DarwinVers - Nonzero if this is a darwin platform: the numeric
/// version of the platform, e.g. 8 = 10.4 (Tiger), 9 = 10.5 (Leopard), etc.
unsigned char DarwinVers; // Is any darwin-x86 platform.
@@ -133,6 +142,9 @@ public:
bool hasSSE4A() const { return HasSSE4A; }
bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
+ bool hasAVX() const { return hasAVX(); }
+ bool hasFMA3() const { return HasFMA3; }
+ bool hasFMA4() const { return HasFMA4; }
bool isBTMemSlow() const { return IsBTMemSlow; }
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 53c46c3..67dcd01 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -36,10 +36,8 @@ X("x86", "32-bit X86: Pentium-Pro and above");
static RegisterTarget<X86_64TargetMachine>
Y("x86-64", "64-bit X86: EM64T and AMD64");
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeX86Target() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeX86Target() { }
// No assembler printer by default
X86TargetMachine::AsmPrinterCtorFn X86TargetMachine::AsmPrinterCtor = 0;
@@ -222,7 +220,8 @@ bool X86TargetMachine::addAssemblyEmitter(PassManagerBase &PM,
// On Darwin, override 64-bit static relocation to pic_ since the
// assembler doesn't support it.
if (DefRelocModel == Reloc::Static &&
- Subtarget.isTargetDarwin() && Subtarget.is64Bit())
+ Subtarget.isTargetDarwin() && Subtarget.is64Bit() &&
+ getCodeModel() == CodeModel::Small)
setRelocationModel(Reloc::PIC_);
assert(AsmPrinterCtor && "AsmPrinter was not linked in");
@@ -319,11 +318,3 @@ bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
return false;
}
-/// symbolicAddressesAreRIPRel - Return true if symbolic addresses are
-/// RIP-relative on this machine, taking into consideration the relocation
-/// model and subtarget. RIP-relative addresses cannot have a separate
-/// base or index register.
-bool X86TargetMachine::symbolicAddressesAreRIPRel() const {
- return getRelocationModel() != Reloc::Static &&
- Subtarget.isPICStyleRIPRel();
-}
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index ecc1d39..ba73ca8 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -91,12 +91,6 @@ public:
virtual bool addSimpleCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm, JITCodeEmitter &JCE);
-
- /// symbolicAddressesAreRIPRel - Return true if symbolic addresses are
- /// RIP-relative on this machine, taking into consideration the relocation
- /// model and subtarget. RIP-relative addresses cannot have a separate
- /// base or index register.
- bool symbolicAddressesAreRIPRel() const;
};
/// X86_32TargetMachine - X86 32-bit target machine.
diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp
index ed4c101..4ab5d75 100644
--- a/lib/Target/XCore/XCoreAsmPrinter.cpp
+++ b/lib/Target/XCore/XCoreAsmPrinter.cpp
@@ -244,9 +244,6 @@ emitGlobal(const GlobalVariable *GV)
// Mark the end of the global
O << "\t.cc_bottom " << name << ".data\n";
- } else {
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
}
}
@@ -375,12 +372,7 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
printBasicBlockLabel(MO.getMBB());
break;
case MachineOperand::MO_GlobalAddress:
- {
- const GlobalValue *GV = MO.getGlobal();
- O << Mang->getValueName(GV);
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
- }
+ O << Mang->getValueName(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
@@ -430,25 +422,8 @@ bool XCoreAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
DW = getAnalysisIfAvailable<DwarfWriter>();
- if (!FileDirective.empty()) {
+ if (!FileDirective.empty())
emitFileDirective(FileDirective);
- }
-
- // Print out type strings for external functions here
- for (Module::const_iterator I = M.begin(), E = M.end();
- I != E; ++I) {
- if (I->isDeclaration() && !I->isIntrinsic()) {
- switch (I->getLinkage()) {
- default:
- assert(0 && "Unexpected linkage");
- case Function::ExternalWeakLinkage:
- ExtWeakSymbols.insert(I);
- // fallthrough
- case Function::ExternalLinkage:
- break;
- }
- }
- }
return Result;
}
@@ -461,8 +436,5 @@ bool XCoreAsmPrinter::doFinalization(Module &M) {
emitGlobal(I);
}
- // Emit final debug information.
- DW->EndModule();
-
return AsmPrinter::doFinalization(M);
}
diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp
index cfd3cd3..09227d9 100644
--- a/lib/Target/XCore/XCoreTargetMachine.cpp
+++ b/lib/Target/XCore/XCoreTargetMachine.cpp
@@ -31,10 +31,8 @@ namespace {
RegisterTarget<XCoreTargetMachine> X("xcore", "XCore");
}
-// Force static initialization when called from llvm/InitializeAllTargets.h
-namespace llvm {
- void InitializeXCoreTarget() { }
-}
+// Force static initialization.
+extern "C" void LLVMInitializeXCoreTarget() { }
const TargetAsmInfo *XCoreTargetMachine::createTargetAsmInfo() const {
return new XCoreTargetAsmInfo(*this);
OpenPOWER on IntegriCloud