aboutsummaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/AArch64/AArch64CallLowering.cpp2
-rw-r--r--lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp9
-rw-r--r--lib/Target/ARM/ARM.td1
-rw-r--r--lib/Target/ARM/ARMCallLowering.cpp2
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp4
-rw-r--r--lib/Target/AVR/AVRFrameLowering.cpp5
-rw-r--r--lib/Target/AVR/AVRRegisterInfo.cpp18
-rw-r--r--lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp10
-rw-r--r--lib/Target/Hexagon/HexagonAsmPrinter.cpp2
-rw-r--r--lib/Target/Hexagon/HexagonISelLowering.cpp7
-rw-r--r--lib/Target/Hexagon/HexagonInstrFormats.td16
-rw-r--r--lib/Target/Hexagon/HexagonInstrFormatsV60.td8
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp128
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.h2
-rw-r--r--lib/Target/Hexagon/HexagonMCInstLower.cpp2
-rw-r--r--lib/Target/Hexagon/HexagonOperands.td4
-rw-r--r--lib/Target/Hexagon/HexagonPseudo.td15
-rw-r--r--lib/Target/Hexagon/HexagonVLIWPacketizer.cpp33
-rw-r--r--lib/Target/Hexagon/HexagonVLIWPacketizer.h4
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp15
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h4
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp10
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h5
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp174
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h9
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp23
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp8
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h6
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp92
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h30
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp90
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h4
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp9
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h8
-rw-r--r--lib/Target/SystemZ/SystemZTargetTransformInfo.cpp7
-rw-r--r--lib/Target/X86/X86.td6
-rw-r--r--lib/Target/X86/X86FastISel.cpp9
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp63
-rw-r--r--lib/Target/X86/X86ISelLowering.h3
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp6
-rw-r--r--lib/Target/X86/X86InstrInfo.td59
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp9
-rw-r--r--lib/Target/X86/X86Schedule.td1
-rw-r--r--lib/Target/X86/X86Subtarget.cpp1
-rw-r--r--lib/Target/X86/X86Subtarget.h4
-rw-r--r--lib/Target/X86/X86WinEHState.cpp2
46 files changed, 629 insertions, 300 deletions
diff --git a/lib/Target/AArch64/AArch64CallLowering.cpp b/lib/Target/AArch64/AArch64CallLowering.cpp
index b2f55a7e1e09..ff3e4c40e2c2 100644
--- a/lib/Target/AArch64/AArch64CallLowering.cpp
+++ b/lib/Target/AArch64/AArch64CallLowering.cpp
@@ -247,7 +247,7 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
unsigned i = 0;
for (auto &Arg : F.args()) {
ArgInfo OrigArg{VRegs[i], Arg.getType()};
- setArgFlags(OrigArg, i + 1, DL, F);
+ setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F);
bool Split = false;
LLT Ty = MRI.getType(VRegs[i]);
unsigned Dst = VRegs[i];
diff --git a/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index 4fb262c6277c..36dcc699d4ea 100644
--- a/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -677,12 +677,19 @@ void AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I) {
}
const Function &ContainingFunction = *I.getParent()->getParent();
+ CallingConv::ID CC = ContainingFunction.getCallingConv();
// Don't promote the alloca to LDS for shader calling conventions as the work
// item ID intrinsics are not supported for these calling conventions.
// Furthermore not all LDS is available for some of the stages.
- if (AMDGPU::isShader(ContainingFunction.getCallingConv()))
+ switch (CC) {
+ case CallingConv::AMDGPU_KERNEL:
+ case CallingConv::SPIR_KERNEL:
+ break;
+ default:
+ DEBUG(dbgs() << " promote alloca to LDS not supported with calling convention.\n");
return;
+ }
const AMDGPUSubtarget &ST =
TM->getSubtarget<AMDGPUSubtarget>(ContainingFunction);
diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
index 005b74a68af3..46fd1f70ee99 100644
--- a/lib/Target/ARM/ARM.td
+++ b/lib/Target/ARM/ARM.td
@@ -577,6 +577,7 @@ def : Processor<"cortex-m0plus", ARMV6Itineraries, [ARMv6m]>;
def : Processor<"cortex-m1", ARMV6Itineraries, [ARMv6m]>;
def : Processor<"sc000", ARMV6Itineraries, [ARMv6m]>;
+def : Processor<"arm1176j-s", ARMV6Itineraries, [ARMv6kz]>;
def : Processor<"arm1176jz-s", ARMV6Itineraries, [ARMv6kz]>;
def : Processor<"arm1176jzf-s", ARMV6Itineraries, [ARMv6kz,
FeatureVFP2,
diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp
index a8188411bf5f..9178c67afa6e 100644
--- a/lib/Target/ARM/ARMCallLowering.cpp
+++ b/lib/Target/ARM/ARMCallLowering.cpp
@@ -354,7 +354,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
unsigned Idx = 0;
for (auto &Arg : F.args()) {
ArgInfo AInfo(VRegs[Idx], Arg.getType());
- setArgFlags(AInfo, Idx + 1, DL, F);
+ setArgFlags(AInfo, Idx + AttributeList::FirstArgIndex, DL, F);
splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo());
Idx++;
}
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index e9df9449103c..7f9fe55a5c38 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -740,7 +740,9 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
unsigned PowerOfTwo = 0;
SDValue NewMulConst;
if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
+ HandleSDNode Handle(Offset);
replaceDAGValue(Offset.getOperand(1), NewMulConst);
+ Offset = Handle.getValue();
ShAmt = PowerOfTwo;
ShOpcVal = ARM_AM::lsl;
}
@@ -1420,7 +1422,9 @@ bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
unsigned PowerOfTwo = 0;
SDValue NewMulConst;
if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
+ HandleSDNode Handle(OffReg);
replaceDAGValue(OffReg.getOperand(1), NewMulConst);
+ OffReg = Handle.getValue();
ShAmt = PowerOfTwo;
}
}
diff --git a/lib/Target/AVR/AVRFrameLowering.cpp b/lib/Target/AVR/AVRFrameLowering.cpp
index 25232d2e47e1..c297865db820 100644
--- a/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/lib/Target/AVR/AVRFrameLowering.cpp
@@ -228,9 +228,8 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
bool AVRFrameLowering::hasFP(const MachineFunction &MF) const {
const AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
- // TODO: We do not always need a frame pointer.
- // This can be optimised.
- return true;
+ return (FuncInfo->getHasSpills() || FuncInfo->getHasAllocas() ||
+ FuncInfo->getHasStackArgs());
}
bool AVRFrameLowering::spillCalleeSavedRegisters(
diff --git a/lib/Target/AVR/AVRRegisterInfo.cpp b/lib/Target/AVR/AVRRegisterInfo.cpp
index 5cc7eaf8add3..2813e24d2ac7 100644
--- a/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -65,12 +65,18 @@ BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
Reserved.set(AVR::SPH);
Reserved.set(AVR::SP);
- // Reserve the frame pointer registers r28 and r29 if the function requires one.
- if (TFI->hasFP(MF)) {
- Reserved.set(AVR::R28);
- Reserved.set(AVR::R29);
- Reserved.set(AVR::R29R28);
- }
+ // We tenatively reserve the frame pointer register r29:r28 because the
+ // function may require one, but we cannot tell until register allocation
+ // is complete, which can be too late.
+ //
+ // Instead we just unconditionally reserve the Y register.
+ //
+ // TODO: Write a pass to enumerate functions which reserved the Y register
+ // but didn't end up needing a frame pointer. In these, we can
+ // convert one or two of the spills inside to use the Y register.
+ Reserved.set(AVR::R28);
+ Reserved.set(AVR::R29);
+ Reserved.set(AVR::R29R28);
return Reserved;
}
diff --git a/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
index 42ff9cc3d18a..b0b2644fffbe 100644
--- a/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
+++ b/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
@@ -307,7 +307,7 @@ public:
bool iss31_1Imm() const { return true; }
bool iss30_2Imm() const { return true; }
bool iss29_3Imm() const { return true; }
- bool iss23_2Imm() const { return CheckImmRange(23, 2, true, true, false); }
+ bool iss27_2Imm() const { return CheckImmRange(27, 2, true, true, false); }
bool iss10_0Imm() const { return CheckImmRange(10, 0, true, false, false); }
bool iss10_6Imm() const { return CheckImmRange(10, 6, true, false, false); }
bool iss9_0Imm() const { return CheckImmRange(9, 0, true, false, false); }
@@ -1292,13 +1292,13 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
case Hexagon::A2_iconst: {
Inst.setOpcode(Hexagon::A2_addi);
MCOperand Reg = Inst.getOperand(0);
- MCOperand S16 = Inst.getOperand(1);
- HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr());
- HexagonMCInstrInfo::setS23_2_reloc(*S16.getExpr());
+ MCOperand S27 = Inst.getOperand(1);
+ HexagonMCInstrInfo::setMustNotExtend(*S27.getExpr());
+ HexagonMCInstrInfo::setS27_2_reloc(*S27.getExpr());
Inst.clear();
Inst.addOperand(Reg);
Inst.addOperand(MCOperand::createReg(Hexagon::R0));
- Inst.addOperand(S16);
+ Inst.addOperand(S27);
break;
}
case Hexagon::M4_mpyrr_addr:
diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp
index c8483f7e6e76..bb5128e7500f 100644
--- a/lib/Target/Hexagon/HexagonAsmPrinter.cpp
+++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp
@@ -298,7 +298,7 @@ void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst,
MCOperand Reg = Inst.getOperand(0);
MCOperand S16 = Inst.getOperand(1);
HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr());
- HexagonMCInstrInfo::setS23_2_reloc(*S16.getExpr());
+ HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr());
Inst.clear();
Inst.addOperand(Reg);
Inst.addOperand(MCOperand::createReg(Hexagon::R0));
diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp
index e5eb059b566f..861af94f1e38 100644
--- a/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1720,8 +1720,13 @@ HexagonTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InFlag);
InFlag = Chain.getValue(1);
+ unsigned Flags =
+ static_cast<const HexagonSubtarget &>(DAG.getSubtarget()).useLongCalls()
+ ? HexagonII::MO_GDPLT | HexagonII::HMOTF_ConstExtended
+ : HexagonII::MO_GDPLT;
+
return GetDynamicTLSAddr(DAG, Chain, GA, InFlag, PtrVT,
- Hexagon::R0, HexagonII::MO_GDPLT);
+ Hexagon::R0, Flags);
}
//
diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td
index 7d1da5c3ba21..709d64585c0b 100644
--- a/lib/Target/Hexagon/HexagonInstrFormats.td
+++ b/lib/Target/Hexagon/HexagonInstrFormats.td
@@ -7,16 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// Maintain list of valid subtargets for each instruction.
-class SubTarget<bits<6> value> {
- bits<6> Value = value;
-}
-
-def HasAnySubT : SubTarget<0x3f>; // 111111
-def HasV5SubT : SubTarget<0x3e>; // 111110
-def HasV55SubT : SubTarget<0x3c>; // 111100
-def HasV60SubT : SubTarget<0x38>; // 111000
-
// Addressing modes for load/store instructions
class AddrModeType<bits<3> value> {
bits<3> Value = value;
@@ -131,12 +121,6 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
bits<2> opExtentAlign = 0;
let TSFlags{34-33} = opExtentAlign; // Alignment exponent before extending.
- // If an instruction is valid on a subtarget, set the corresponding
- // bit from validSubTargets.
- // By default, instruction is valid on all subtargets.
- SubTarget validSubTargets = HasAnySubT;
- let TSFlags{40-35} = validSubTargets.Value;
-
// Addressing mode for load/store instructions.
AddrModeType addrMode = NoAddrMode;
let TSFlags{43-41} = addrMode.Value;
diff --git a/lib/Target/Hexagon/HexagonInstrFormatsV60.td b/lib/Target/Hexagon/HexagonInstrFormatsV60.td
index 1c46ae77b6c7..b913727972e5 100644
--- a/lib/Target/Hexagon/HexagonInstrFormatsV60.td
+++ b/lib/Target/Hexagon/HexagonInstrFormatsV60.td
@@ -15,8 +15,6 @@
// Instruction Classes Definitions +
//----------------------------------------------------------------------------//
-let validSubTargets = HasV60SubT in
-{
class CVI_VA_Resource<dag outs, dag ins, string asmstr,
list<dag> pattern = [], string cstr = "",
InstrItinClass itin = CVI_VA>
@@ -184,10 +182,7 @@ class CVI_HIST_Resource<dag outs, dag ins, string asmstr,
InstrItinClass itin = CVI_HIST>
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeCVI_HIST>,
OpcodeHexagon, Requires<[HasV60T, UseHVX]>;
-}
-let validSubTargets = HasV60SubT in
-{
class CVI_VA_Resource1<dag outs, dag ins, string asmstr,
list<dag> pattern = [], string cstr = "",
InstrItinClass itin = CVI_VA>
@@ -205,6 +200,3 @@ class CVI_HIST_Resource1<dag outs, dag ins, string asmstr,
InstrItinClass itin = CVI_HIST>
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeCVI_HIST>,
Requires<[HasV60T, UseHVX]>;
-}
-
-
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index b265a883da5c..852bfb1b4f54 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -869,6 +869,9 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FI);
unsigned KillFlag = getKillRegState(isKill);
+ bool HasAlloca = MFI.hasVarSizedObjects();
+ const auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ const HexagonFrameLowering &HFI = *HST.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
@@ -899,24 +902,36 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 128 ? Hexagon::V6_vS32Ub_ai_128B
: Hexagon::V6_vS32b_ai_128B;
BuildMI(MBB, I, DL, get(Opc))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 64 ? Hexagon::V6_vS32Ub_ai
: Hexagon::V6_vS32b_ai;
BuildMI(MBB, I, DL, get(Opc))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 64 ? Hexagon::PS_vstorerwu_ai
: Hexagon::PS_vstorerw_ai;
BuildMI(MBB, I, DL, get(Opc))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 128 ? Hexagon::PS_vstorerwu_ai_128B
: Hexagon::PS_vstorerw_ai_128B;
BuildMI(MBB, I, DL, get(Opc))
@@ -935,6 +950,9 @@ void HexagonInstrInfo::loadRegFromStackSlot(
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FI);
+ bool HasAlloca = MFI.hasVarSizedObjects();
+ const auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ const HexagonFrameLowering &HFI = *HST.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
@@ -959,21 +977,33 @@ void HexagonInstrInfo::loadRegFromStackSlot(
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 128 ? Hexagon::PS_vloadrwu_ai_128B
: Hexagon::PS_vloadrw_ai_128B;
BuildMI(MBB, I, DL, get(Opc), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 128 ? Hexagon::V6_vL32Ub_ai_128B
: Hexagon::V6_vL32b_ai_128B;
BuildMI(MBB, I, DL, get(Opc), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 64 ? Hexagon::V6_vL32Ub_ai
: Hexagon::V6_vL32b_ai;
BuildMI(MBB, I, DL, get(Opc), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
+ // If there are variable-sized objects, spills will not be aligned.
+ if (HasAlloca)
+ Align = HFI.getStackAlignment();
unsigned Opc = Align < 64 ? Hexagon::PS_vloadrwu_ai
: Hexagon::PS_vloadrw_ai;
BuildMI(MBB, I, DL, get(Opc), DestReg)
@@ -1110,8 +1140,9 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc),
HRI.getSubReg(DstReg, Hexagon::vsub_lo))
- .add(MI.getOperand(1))
- .addImm(MI.getOperand(2).getImm());
+ .add(MI.getOperand(1))
+ .addImm(MI.getOperand(2).getImm())
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MI1New->getOperand(1).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpc), HRI.getSubReg(DstReg, Hexagon::vsub_hi))
.add(MI.getOperand(1))
@@ -1940,7 +1971,7 @@ bool HexagonInstrInfo::isDeallocRet(const MachineInstr &MI) const {
case Hexagon::L4_return_fnew_pnt :
case Hexagon::L4_return_tnew_pt :
case Hexagon::L4_return_fnew_pt :
- return true;
+ return true;
}
return false;
}
@@ -1967,12 +1998,12 @@ bool HexagonInstrInfo::isDependent(const MachineInstr &ProdMI,
if (RegA == RegB)
return true;
- if (Hexagon::DoubleRegsRegClass.contains(RegA))
+ if (TargetRegisterInfo::isPhysicalRegister(RegA))
for (MCSubRegIterator SubRegs(RegA, &HRI); SubRegs.isValid(); ++SubRegs)
if (RegB == *SubRegs)
return true;
- if (Hexagon::DoubleRegsRegClass.contains(RegB))
+ if (TargetRegisterInfo::isPhysicalRegister(RegB))
for (MCSubRegIterator SubRegs(RegB, &HRI); SubRegs.isValid(); ++SubRegs)
if (RegA == *SubRegs)
return true;
@@ -2139,7 +2170,7 @@ bool HexagonInstrInfo::isJumpR(const MachineInstr &MI) const {
bool HexagonInstrInfo::isJumpWithinBranchRange(const MachineInstr &MI,
unsigned offset) const {
// This selection of jump instructions matches to that what
- // AnalyzeBranch can parse, plus NVJ.
+ // analyzeBranch can parse, plus NVJ.
if (isNewValueJump(MI)) // r9:2
return isInt<11>(offset);
@@ -2666,6 +2697,7 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::L2_loadrh_io:
case Hexagon::L2_loadruh_io:
case Hexagon::S2_storerh_io:
+ case Hexagon::S2_storerf_io:
return (Offset >= Hexagon_MEMH_OFFSET_MIN) &&
(Offset <= Hexagon_MEMH_OFFSET_MAX);
@@ -2876,6 +2908,11 @@ bool HexagonInstrInfo::getMemOpBaseRegImmOfs(MachineInstr &LdSt,
/// \brief Can these instructions execute at the same time in a bundle.
bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr &First,
const MachineInstr &Second) const {
+ if (Second.mayStore() && First.getOpcode() == Hexagon::S2_allocframe) {
+ const MachineOperand &Op = Second.getOperand(0);
+ if (Op.isReg() && Op.isUse() && Op.getReg() == Hexagon::R29)
+ return true;
+ }
if (DisableNVSchedule)
return false;
if (mayBeNewStore(Second)) {
@@ -3000,13 +3037,9 @@ bool HexagonInstrInfo::producesStall(const MachineInstr &MI,
MachineBasicBlock::const_instr_iterator MII = BII;
MachineBasicBlock::const_instr_iterator MIE = MII->getParent()->instr_end();
- if (!MII->isBundle()) {
+ if (!(*MII).isBundle()) {
const MachineInstr &J = *MII;
- if (!isV60VectorInstruction(J))
- return false;
- else if (isVecUsableNextPacket(J, MI))
- return false;
- return true;
+ return producesStall(J, MI);
}
for (++MII; MII != MIE && MII->isInsideBundle(); ++MII) {
@@ -3034,12 +3067,14 @@ bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI,
}
bool HexagonInstrInfo::PredOpcodeHasJMP_c(unsigned Opcode) const {
- return (Opcode == Hexagon::J2_jumpt) ||
- (Opcode == Hexagon::J2_jumpf) ||
- (Opcode == Hexagon::J2_jumptnew) ||
- (Opcode == Hexagon::J2_jumpfnew) ||
- (Opcode == Hexagon::J2_jumptnewpt) ||
- (Opcode == Hexagon::J2_jumpfnewpt);
+ return Opcode == Hexagon::J2_jumpt ||
+ Opcode == Hexagon::J2_jumptpt ||
+ Opcode == Hexagon::J2_jumpf ||
+ Opcode == Hexagon::J2_jumpfpt ||
+ Opcode == Hexagon::J2_jumptnew ||
+ Opcode == Hexagon::J2_jumpfnew ||
+ Opcode == Hexagon::J2_jumptnewpt ||
+ Opcode == Hexagon::J2_jumpfnewpt;
}
bool HexagonInstrInfo::predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const {
@@ -3341,9 +3376,30 @@ int HexagonInstrInfo::getDotCurOp(const MachineInstr &MI) const {
return 0;
}
+// Return the regular version of the .cur instruction.
+int HexagonInstrInfo::getNonDotCurOp(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ default: llvm_unreachable("Unknown .cur type");
+ case Hexagon::V6_vL32b_cur_pi:
+ return Hexagon::V6_vL32b_pi;
+ case Hexagon::V6_vL32b_cur_ai:
+ return Hexagon::V6_vL32b_ai;
+ //128B
+ case Hexagon::V6_vL32b_cur_pi_128B:
+ return Hexagon::V6_vL32b_pi_128B;
+ case Hexagon::V6_vL32b_cur_ai_128B:
+ return Hexagon::V6_vL32b_ai_128B;
+ }
+ return 0;
+}
+
+
// The diagram below shows the steps involved in the conversion of a predicated
// store instruction to its .new predicated new-value form.
//
+// Note: It doesn't include conditional new-value stores as they can't be
+// converted to .new predicate.
+//
// p.new NV store [ if(p0.new)memw(R0+#0)=R2.new ]
// ^ ^
// / \ (not OK. it will cause new-value store to be
@@ -3564,11 +3620,11 @@ int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI,
}
int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
+ const MachineFunction &MF = *MI.getParent()->getParent();
+ const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
int NewOp = MI.getOpcode();
if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form
NewOp = Hexagon::getPredOldOpcode(NewOp);
- const MachineFunction &MF = *MI.getParent()->getParent();
- const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
// All Hexagon architectures have prediction bits on dot-new branches,
// but only Hexagon V60+ has prediction bits on dot-old ones. Make sure
// to pick the right opcode when converting back to dot-old.
@@ -3596,6 +3652,21 @@ int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
NewOp = Hexagon::getNonNVStore(NewOp);
assert(NewOp >= 0 && "Couldn't change new-value store to its old form.");
}
+
+ if (HST.hasV60TOps())
+ return NewOp;
+
+ // Subtargets prior to V60 didn't support 'taken' forms of predicated jumps.
+ switch (NewOp) {
+ case Hexagon::J2_jumpfpt:
+ return Hexagon::J2_jumpf;
+ case Hexagon::J2_jumptpt:
+ return Hexagon::J2_jumpt;
+ case Hexagon::J2_jumprfpt:
+ return Hexagon::J2_jumprf;
+ case Hexagon::J2_jumprtpt:
+ return Hexagon::J2_jumprt;
+ }
return NewOp;
}
@@ -3947,18 +4018,6 @@ short HexagonInstrInfo::getEquivalentHWInstr(const MachineInstr &MI) const {
return Hexagon::getRealHWInstr(MI.getOpcode(), Hexagon::InstrType_Real);
}
-// Return first non-debug instruction in the basic block.
-MachineInstr *HexagonInstrInfo::getFirstNonDbgInst(MachineBasicBlock *BB)
- const {
- for (auto MII = BB->instr_begin(), End = BB->instr_end(); MII != End; MII++) {
- MachineInstr &MI = *MII;
- if (MI.isDebugValue())
- continue;
- return &MI;
- }
- return nullptr;
-}
-
unsigned HexagonInstrInfo::getInstrTimingClassLatency(
const InstrItineraryData *ItinData, const MachineInstr &MI) const {
// Default to one cycle for no itinerary. However, an "empty" itinerary may
@@ -4139,11 +4198,6 @@ unsigned HexagonInstrInfo::getUnits(const MachineInstr &MI) const {
return IS.getUnits();
}
-unsigned HexagonInstrInfo::getValidSubTargets(const unsigned Opcode) const {
- const uint64_t F = get(Opcode).TSFlags;
- return (F >> HexagonII::validSubTargetPos) & HexagonII::validSubTargetMask;
-}
-
// Calculate size of the basic block without debug instructions.
unsigned HexagonInstrInfo::nonDbgBBSize(const MachineBasicBlock *BB) const {
return nonDbgMICount(BB->instr_begin(), BB->instr_end());
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h
index b268c7a28171..21b4f738f6e8 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -399,6 +399,7 @@ public:
const MachineInstr &GB) const;
int getCondOpcode(int Opc, bool sense) const;
int getDotCurOp(const MachineInstr &MI) const;
+ int getNonDotCurOp(const MachineInstr &MI) const;
int getDotNewOp(const MachineInstr &MI) const;
int getDotNewPredJumpOp(const MachineInstr &MI,
const MachineBranchProbabilityInfo *MBPI) const;
@@ -424,7 +425,6 @@ public:
unsigned getSize(const MachineInstr &MI) const;
uint64_t getType(const MachineInstr &MI) const;
unsigned getUnits(const MachineInstr &MI) const;
- unsigned getValidSubTargets(const unsigned Opcode) const;
/// getInstrTimingClassLatency - Compute the instruction latency of a given
/// instruction using Timing Class information, if available.
diff --git a/lib/Target/Hexagon/HexagonMCInstLower.cpp b/lib/Target/Hexagon/HexagonMCInstLower.cpp
index 7189b5a52c42..072501d8260d 100644
--- a/lib/Target/Hexagon/HexagonMCInstLower.cpp
+++ b/lib/Target/Hexagon/HexagonMCInstLower.cpp
@@ -39,7 +39,7 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
// Populate the relocation type based on Hexagon target flags
// set on an operand
MCSymbolRefExpr::VariantKind RelocationType;
- switch (MO.getTargetFlags()) {
+ switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) {
default:
RelocationType = MCSymbolRefExpr::VK_None;
break;
diff --git a/lib/Target/Hexagon/HexagonOperands.td b/lib/Target/Hexagon/HexagonOperands.td
index f87a1b8e424d..f80e0ef9e39f 100644
--- a/lib/Target/Hexagon/HexagonOperands.td
+++ b/lib/Target/Hexagon/HexagonOperands.td
@@ -14,8 +14,8 @@ def f64Imm : Operand<f64> { let ParserMatchClass = f64ImmOperand; }
def s8_0Imm64Pred : PatLeaf<(i64 imm), [{ return isInt<8>(N->getSExtValue()); }]>;
def s9_0ImmOperand : AsmOperandClass { let Name = "s9_0Imm"; }
def s9_0Imm : Operand<i32> { let ParserMatchClass = s9_0ImmOperand; }
-def s23_2ImmOperand : AsmOperandClass { let Name = "s23_2Imm"; let RenderMethod = "addSignedImmOperands"; }
-def s23_2Imm : Operand<i32> { let ParserMatchClass = s23_2ImmOperand; }
+def s27_2ImmOperand : AsmOperandClass { let Name = "s27_2Imm"; let RenderMethod = "addSignedImmOperands"; }
+def s27_2Imm : Operand<i32> { let ParserMatchClass = s27_2ImmOperand; }
def r32_0ImmPred : PatLeaf<(i32 imm), [{
int64_t v = (int64_t)N->getSExtValue();
return isInt<32>(v);
diff --git a/lib/Target/Hexagon/HexagonPseudo.td b/lib/Target/Hexagon/HexagonPseudo.td
index 5a720e794562..2e8def572c4b 100644
--- a/lib/Target/Hexagon/HexagonPseudo.td
+++ b/lib/Target/Hexagon/HexagonPseudo.td
@@ -14,8 +14,11 @@ let PrintMethod = "printGlobalOperand" in {
let isPseudo = 1 in {
let isCodeGenOnly = 0 in
-def A2_iconst : Pseudo<(outs IntRegs:$Rd32), (ins s23_2Imm:$Ii), "${Rd32}=iconst(#${Ii})">;
-def DUPLEX_Pseudo : InstHexagon<(outs), (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
+def A2_iconst : Pseudo<(outs IntRegs:$Rd32),
+ (ins s27_2Imm:$Ii), "${Rd32}=iconst(#${Ii})">;
+
+def DUPLEX_Pseudo : InstHexagon<(outs),
+ (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
}
let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
@@ -321,7 +324,7 @@ def LDriw_mod : LDInst<(outs ModRegs:$dst),
// Vector load
let Predicates = [HasV60T, UseHVX] in
-let mayLoad = 1, validSubTargets = HasV60SubT, hasSideEffects = 0 in
+let mayLoad = 1, hasSideEffects = 0 in
class V6_LDInst<dag outs, dag ins, string asmstr, list<dag> pattern = [],
string cstr = "", InstrItinClass itin = CVI_VM_LD,
IType type = TypeCVI_VM_LD>
@@ -329,7 +332,7 @@ let mayLoad = 1, validSubTargets = HasV60SubT, hasSideEffects = 0 in
// Vector store
let Predicates = [HasV60T, UseHVX] in
-let mayStore = 1, validSubTargets = HasV60SubT, hasSideEffects = 0 in
+let mayStore = 1, hasSideEffects = 0 in
class V6_STInst<dag outs, dag ins, string asmstr, list<dag> pattern = [],
string cstr = "", InstrItinClass itin = CVI_VM_ST,
IType type = TypeCVI_VM_ST>
@@ -415,7 +418,7 @@ let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
// Vector load/store pseudos
-let isPseudo = 1, isCodeGenOnly = 1, validSubTargets = HasV60SubT in
+let isPseudo = 1, isCodeGenOnly = 1 in
class STrivv_template<RegisterClass RC>
: V6_STInst<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src), "", []>;
@@ -429,7 +432,7 @@ def PS_vstorerwu_ai_128B: STrivv_template<VecDblRegs128B>,
Requires<[HasV60T,UseHVXDbl]>;
-let isPseudo = 1, isCodeGenOnly = 1, validSubTargets = HasV60SubT in
+let isPseudo = 1, isCodeGenOnly = 1 in
class LDrivv_template<RegisterClass RC>
: V6_LDInst<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off), "", []>;
diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
index 3a789a5f7e0b..bf1dce67bd0a 100644
--- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
+++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
@@ -356,7 +356,7 @@ void HexagonPacketizerList::cleanUpDotCur() {
MachineInstr *MI = nullptr;
for (auto BI : CurrentPacketMIs) {
DEBUG(dbgs() << "Cleanup packet has "; BI->dump(););
- if (BI->getOpcode() == Hexagon::V6_vL32b_cur_ai) {
+ if (HII->isDotCurInst(*BI)) {
MI = BI;
continue;
}
@@ -369,7 +369,7 @@ void HexagonPacketizerList::cleanUpDotCur() {
if (!MI)
return;
// We did not find a use of the CUR, so de-cur it.
- MI->setDesc(HII->get(Hexagon::V6_vL32b_ai));
+ MI->setDesc(HII->get(HII->getNonDotCurOp(*MI)));
DEBUG(dbgs() << "Demoted CUR "; MI->dump(););
}
@@ -1579,14 +1579,13 @@ MachineBasicBlock::iterator
HexagonPacketizerList::addToPacket(MachineInstr &MI) {
MachineBasicBlock::iterator MII = MI.getIterator();
MachineBasicBlock *MBB = MI.getParent();
- if (MI.isImplicitDef()) {
- unsigned R = MI.getOperand(0).getReg();
- if (Hexagon::IntRegsRegClass.contains(R)) {
- MCSuperRegIterator S(R, HRI, false);
- MI.addOperand(MachineOperand::CreateReg(*S, true, true));
- }
+
+ if (CurrentPacketMIs.size() == 0)
+ PacketStalls = false;
+ PacketStalls |= producesStall(MI);
+
+ if (MI.isImplicitDef())
return MII;
- }
assert(ResourceTracker->canReserveResources(MI));
bool ExtMI = HII->isExtended(MI) || HII->isConstExtended(MI);
@@ -1677,6 +1676,11 @@ static bool isDependent(const MachineInstr &ProdMI,
// V60 forward scheduling.
bool HexagonPacketizerList::producesStall(const MachineInstr &I) {
+ // If the packet already stalls, then ignore the stall from a subsequent
+ // instruction in the same packet.
+ if (PacketStalls)
+ return false;
+
// Check whether the previous packet is in a different loop. If this is the
// case, there is little point in trying to avoid a stall because that would
// favor the rare case (loop entry) over the common case (loop iteration).
@@ -1699,6 +1703,7 @@ bool HexagonPacketizerList::producesStall(const MachineInstr &I) {
if (isDependent(*J, I) && !HII->isVecUsableNextPacket(*J, I))
return true;
}
+
return false;
}
@@ -1721,6 +1726,16 @@ bool HexagonPacketizerList::producesStall(const MachineInstr &I) {
}
}
+ // Check if the latency is greater than one between this instruction and any
+ // instruction in the previous packet.
+ SUnit *SUI = MIToSUnit[const_cast<MachineInstr *>(&I)];
+ for (auto J : OldPacketMIs) {
+ SUnit *SUJ = MIToSUnit[J];
+ for (auto &Pred : SUI->Preds)
+ if (Pred.getSUnit() == SUJ && Pred.getLatency() > 1)
+ return true;
+ }
+
return false;
}
diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.h b/lib/Target/Hexagon/HexagonVLIWPacketizer.h
index 3f28dc5b79ce..adb92b6dc855 100644
--- a/lib/Target/Hexagon/HexagonVLIWPacketizer.h
+++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.h
@@ -34,6 +34,10 @@ class HexagonPacketizerList : public VLIWPacketizerList {
// Track MIs with ignored dependence.
std::vector<MachineInstr*> IgnoreDepMIs;
+ // Set to true if the packet contains an instruction that stalls with an
+ // instruction from the previous packet.
+ bool PacketStalls = false;
+
protected:
/// \brief A handle to the branch probability pass.
const MachineBranchProbabilityInfo *MBPI;
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
index c3b6eb19828b..904403543e18 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
@@ -184,7 +184,11 @@ public:
{ "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
- { "fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
+ { "fixup_Hexagon_TPREL_11_X", 0, 32, 0 },
+ { "fixup_Hexagon_GD_PLT_B22_PCREL_X",0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Hexagon_GD_PLT_B32_PCREL_X",0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Hexagon_LD_PLT_B22_PCREL_X",0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Hexagon_LD_PLT_B32_PCREL_X",0, 32, MCFixupKindInfo::FKF_IsPCRel }
};
if (Kind < FirstTargetFixupKind)
@@ -291,6 +295,11 @@ public:
case fixup_Hexagon_32_PCREL:
case fixup_Hexagon_6_PCREL_X:
case fixup_Hexagon_23_REG:
+ case fixup_Hexagon_27_REG:
+ case fixup_Hexagon_GD_PLT_B22_PCREL_X:
+ case fixup_Hexagon_GD_PLT_B32_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B22_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B32_PCREL_X:
// These relocations should always have a relocation recorded
IsResolved = false;
return;
@@ -347,6 +356,8 @@ public:
case fixup_Hexagon_B9_PCREL_X:
case fixup_Hexagon_B7_PCREL:
case fixup_Hexagon_B7_PCREL_X:
+ case fixup_Hexagon_GD_PLT_B32_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B32_PCREL_X:
return 4;
}
}
@@ -374,6 +385,8 @@ public:
break;
case fixup_Hexagon_B32_PCREL_X:
+ case fixup_Hexagon_GD_PLT_B32_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B32_PCREL_X:
Value >>= 6;
break;
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
index 53d8b04c50a5..adb546dc2140 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
@@ -128,10 +128,6 @@ namespace HexagonII {
ExtentAlignPos = 33,
ExtentAlignMask = 0x3,
- // Valid subtargets
- validSubTargetPos = 35,
- validSubTargetMask = 0x3f,
-
// Addressing mode for load/store instructions.
AddrModePos = 41,
AddrModeMask = 0x7,
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
index 944e235e72f2..b975e3131094 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
@@ -284,6 +284,16 @@ unsigned HexagonELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_HEX_TPREL_11_X;
case fixup_Hexagon_23_REG:
return ELF::R_HEX_23_REG;
+ case fixup_Hexagon_27_REG:
+ return ELF::R_HEX_27_REG;
+ case fixup_Hexagon_GD_PLT_B22_PCREL_X:
+ return ELF::R_HEX_GD_PLT_B22_PCREL_X;
+ case fixup_Hexagon_GD_PLT_B32_PCREL_X:
+ return ELF::R_HEX_GD_PLT_B32_PCREL_X;
+ case fixup_Hexagon_LD_PLT_B22_PCREL_X:
+ return ELF::R_HEX_LD_PLT_B22_PCREL_X;
+ case fixup_Hexagon_LD_PLT_B32_PCREL_X:
+ return ELF::R_HEX_LD_PLT_B32_PCREL_X;
}
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h b/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
index 4c97ebbdd346..347327669ad9 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
@@ -111,6 +111,11 @@ enum Fixups {
fixup_Hexagon_TPREL_16_X,
fixup_Hexagon_TPREL_11_X,
fixup_Hexagon_23_REG,
+ fixup_Hexagon_27_REG,
+ fixup_Hexagon_GD_PLT_B22_PCREL_X,
+ fixup_Hexagon_GD_PLT_B32_PCREL_X,
+ fixup_Hexagon_LD_PLT_B22_PCREL_X,
+ fixup_Hexagon_LD_PLT_B32_PCREL_X,
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
index 33d73f1819cd..3bb658b84451 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
@@ -113,7 +113,7 @@ void HexagonMCChecker::init(MCInst const &MCI) {
// The instruction table models the USR.OVF flag, which can be
// implicitly modified more than once, but cannot be modified in the
// same packet with an instruction that modifies is explicitly. Deal
- // with such situ- ations individually.
+ // with such situations individually.
SoftDefs.insert(R);
else if (isPredicateRegister(R) &&
HexagonMCInstrInfo::isPredicateLate(MCII, MCI))
@@ -159,12 +159,6 @@ void HexagonMCChecker::init(MCInst const &MCI) {
isPredicateRegister(*SRI))
// Some insns produce predicates too late to be used in the same packet.
LatePreds.insert(*SRI);
- else if (i == 0 && HexagonMCInstrInfo::isCVINew(MCII, MCI) &&
- MCID.mayLoad())
- // Current loads should be used in the same packet.
- // TODO: relies on the impossibility of a current and a temporary loads
- // in the same packet.
- CurDefs.insert(*SRI), Defs[*SRI].insert(PredSense(PredReg, isTrue));
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) ==
HexagonII::TypeCVI_VM_TMP_LD)
// Temporary loads should be used in the same packet, but don't commit
@@ -202,9 +196,8 @@ void HexagonMCChecker::init(MCInst const &MCI) {
if (HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) {
unsigned R2 = HexagonMCInstrInfo::getNewValueOperand2(MCII, MCI).getReg();
- for (MCRegAliasIterator SRI(R2, &RI,
- !MCSubRegIterator(R2, &RI).isValid());
- SRI.isValid(); ++SRI)
+ bool HasSubRegs = MCSubRegIterator(R2, &RI).isValid();
+ for (MCRegAliasIterator SRI(R2, &RI, !HasSubRegs); SRI.isValid(); ++SRI)
if (!MCSubRegIterator(*SRI, &RI).isValid())
NewDefs[*SRI].push_back(NewSense::Def(
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
@@ -252,6 +245,8 @@ bool HexagonMCChecker::check(bool FullCheck) {
bool chkNV = checkNewValues();
bool chkR = checkRegisters();
bool chkRRO = checkRegistersReadOnly();
+ bool chkELB = checkEndloopBranches();
+ checkRegisterCurDefs();
bool chkS = checkSolo();
bool chkSh = true;
if (FullCheck)
@@ -259,11 +254,106 @@ bool HexagonMCChecker::check(bool FullCheck) {
bool chkSl = true;
if (FullCheck)
chkSl = checkSlots();
- bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl;
+ bool chkAXOK = checkAXOK();
+ bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkELB && chkS &&
+ chkSh && chkSl && chkAXOK;
return chk;
}
+bool HexagonMCChecker::checkEndloopBranches() {
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
+ if (Desc.isBranch() || Desc.isCall()) {
+ auto Inner = HexagonMCInstrInfo::isInnerLoop(MCB);
+ if (Inner || HexagonMCInstrInfo::isOuterLoop(MCB)) {
+ reportError(I.getLoc(),
+ llvm::Twine("packet marked with `:endloop") +
+ (Inner ? "0" : "1") + "' " +
+ "cannot contain instructions that modify register " +
+ "`" + llvm::Twine(RI.getName(Hexagon::PC)) + "'");
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+namespace {
+bool isDuplexAGroup(unsigned Opcode) {
+ switch (Opcode) {
+ case Hexagon::SA1_addi:
+ case Hexagon::SA1_addrx:
+ case Hexagon::SA1_addsp:
+ case Hexagon::SA1_and1:
+ case Hexagon::SA1_clrf:
+ case Hexagon::SA1_clrfnew:
+ case Hexagon::SA1_clrt:
+ case Hexagon::SA1_clrtnew:
+ case Hexagon::SA1_cmpeqi:
+ case Hexagon::SA1_combine0i:
+ case Hexagon::SA1_combine1i:
+ case Hexagon::SA1_combine2i:
+ case Hexagon::SA1_combine3i:
+ case Hexagon::SA1_combinerz:
+ case Hexagon::SA1_combinezr:
+ case Hexagon::SA1_dec:
+ case Hexagon::SA1_inc:
+ case Hexagon::SA1_seti:
+ case Hexagon::SA1_setin1:
+ case Hexagon::SA1_sxtb:
+ case Hexagon::SA1_sxth:
+ case Hexagon::SA1_tfr:
+ case Hexagon::SA1_zxtb:
+ case Hexagon::SA1_zxth:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
+ unsigned Result = 0;
+ unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
+ if (Type == HexagonII::TypeDUPLEX) {
+ unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode();
+ unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode();
+ Result += !isDuplexAGroup(subInst0Opcode);
+ Result += !isDuplexAGroup(subInst1Opcode);
+ } else
+ Result +=
+ Type != HexagonII::TypeALU32_2op && Type != HexagonII::TypeALU32_3op &&
+ Type != HexagonII::TypeALU32_ADDI && Type != HexagonII::TypeS_2op &&
+ Type != HexagonII::TypeS_3op &&
+ (Type != HexagonII::TypeALU64 || HexagonMCInstrInfo::isFloat(MCII, ID));
+ return Result != 0;
+}
+} // namespace
+
+bool HexagonMCChecker::checkAXOK() {
+ MCInst const *HasSoloAXInst = nullptr;
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ if (HexagonMCInstrInfo::isSoloAX(MCII, I)) {
+ HasSoloAXInst = &I;
+ }
+ }
+ if (!HasSoloAXInst)
+ return true;
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) {
+ reportError(
+ HasSoloAXInst->getLoc(),
+ llvm::Twine("Instruction can only be in a packet with ALU or "
+ "non-FPU XTYPE instructions"));
+ reportError(I.getLoc(),
+ llvm::Twine("Not an ALU or non-FPU XTYPE instruction"));
+ return false;
+ }
+ }
+ return true;
+}
+
bool HexagonMCChecker::checkSlots() {
unsigned slotsUsed = 0;
for (auto HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
@@ -309,16 +399,6 @@ bool HexagonMCChecker::checkBranches() {
}
}
- if (Branches) // FIXME: should "Defs.count(Hexagon::PC)" be here too?
- if (HexagonMCInstrInfo::isInnerLoop(MCB) ||
- HexagonMCInstrInfo::isOuterLoop(MCB)) {
- // Error out if there's any branch in a loop-end packet.
- Twine N(HexagonMCInstrInfo::isInnerLoop(MCB) ? '0' : '1');
- reportError("packet marked with `:endloop" + N + "' " +
- "cannot contain instructions that modify register " + "`" +
- llvm::Twine(RI.getName(Hexagon::PC)) + "'");
- return false;
- }
if (Branches > 1)
if (!hasConditional || Conditional > Unconditional) {
// Error out if more than one unconditional branch or
@@ -396,6 +476,31 @@ bool HexagonMCChecker::checkRegistersReadOnly() {
return true;
}
+bool HexagonMCChecker::registerUsed(unsigned Register) {
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
+ for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, I).getNumDefs(),
+ n = I.getNumOperands();
+ j < n; ++j) {
+ MCOperand const &Operand = I.getOperand(j);
+ if (Operand.isReg() && Operand.getReg() == Register)
+ return true;
+ }
+ return false;
+}
+
+void HexagonMCChecker::checkRegisterCurDefs() {
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
+ HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
+ unsigned Register = I.getOperand(0).getReg();
+ if (!registerUsed(Register))
+ reportWarning("Register `" + llvm::Twine(RI.getName(Register)) +
+ "' used with `.cur' "
+ "but not used in the same packet");
+ }
+ }
+}
+
// Check for legal register uses and definitions.
bool HexagonMCChecker::checkRegisters() {
// Check for proper register definitions.
@@ -447,8 +552,7 @@ bool HexagonMCChecker::checkRegisters() {
if (PM.count(P) && PM.size() > 2) {
// Error out on conditional changes based on the same predicate
// multiple times
- // (e.g., "{ if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =...
- // }").
+ // (e.g., "if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =...").
reportErrorRegisters(R);
return false;
}
@@ -456,19 +560,6 @@ bool HexagonMCChecker::checkRegisters() {
}
}
- // Check for use of current definitions.
- for (const auto &I : CurDefs) {
- unsigned R = I;
-
- if (!Uses.count(R)) {
- // Warn on an unused current definition.
- reportWarning("register `" + llvm::Twine(RI.getName(R)) +
- "' used with `.cur' "
- "but not used in the same packet");
- return true;
- }
- }
-
// Check for use of temporary definitions.
for (const auto &I : TmpDefs) {
unsigned R = I;
@@ -499,12 +590,11 @@ bool HexagonMCChecker::checkRegisters() {
// Check for legal use of solo insns.
bool HexagonMCChecker::checkSolo() {
if (HexagonMCInstrInfo::bundleSize(MCB) > 1)
- for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
- if (llvm::HexagonMCInstrInfo::isSolo(MCII, *I.getInst())) {
- SMLoc Loc = I.getInst()->getLoc();
- reportError(Loc, "Instruction is marked `isSolo' and "
- "cannot have other instructions in "
- "the same packet");
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ if (llvm::HexagonMCInstrInfo::isSolo(MCII, I)) {
+ reportError(I.getLoc(), "Instruction is marked `isSolo' and "
+ "cannot have other instructions in "
+ "the same packet");
return false;
}
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
index d0238691cdc0..027f78b4899c 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
@@ -78,10 +78,6 @@ class HexagonMCChecker {
typedef std::set<unsigned>::iterator SoftDefsIterator;
std::set<unsigned> SoftDefs;
- /// Set of current definitions committed to the register file.
- typedef std::set<unsigned>::iterator CurDefsIterator;
- std::set<unsigned> CurDefs;
-
/// Set of temporary definitions not committed to the register file.
typedef std::set<unsigned>::iterator TmpDefsIterator;
std::set<unsigned> TmpDefs;
@@ -110,15 +106,20 @@ class HexagonMCChecker {
void init(MCInst const &);
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
+ bool registerUsed(unsigned Register);
+
// Checks performed.
bool checkBranches();
bool checkPredicates();
bool checkNewValues();
bool checkRegisters();
bool checkRegistersReadOnly();
+ bool checkEndloopBranches();
+ void checkRegisterCurDefs();
bool checkSolo();
bool checkShuffle();
bool checkSlots();
+ bool checkAXOK();
static void compoundRegisterMap(unsigned &);
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
index c0956520de73..dfb5f4cc8260 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
@@ -199,6 +199,11 @@ Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits(
return Hexagon::fixup_Hexagon_IE_GOT_32_6_X;
case MCSymbolRefExpr::VK_Hexagon_PCREL:
return Hexagon::fixup_Hexagon_B32_PCREL_X;
+ case MCSymbolRefExpr::VK_Hexagon_GD_PLT:
+ return Hexagon::fixup_Hexagon_GD_PLT_B32_PCREL_X;
+ case MCSymbolRefExpr::VK_Hexagon_LD_PLT:
+ return Hexagon::fixup_Hexagon_LD_PLT_B32_PCREL_X;
+
case MCSymbolRefExpr::VK_None: {
auto Insts = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle);
for (auto I = Insts.begin(), N = Insts.end(); I != N; ++I) {
@@ -318,6 +323,8 @@ namespace {
case fixup_Hexagon_PLT_B22_PCREL:
case fixup_Hexagon_GD_PLT_B22_PCREL:
case fixup_Hexagon_LD_PLT_B22_PCREL:
+ case fixup_Hexagon_GD_PLT_B22_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B22_PCREL_X:
case fixup_Hexagon_6_PCREL_X:
return true;
default:
@@ -414,10 +421,12 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
case 22:
switch (kind) {
case MCSymbolRefExpr::VK_Hexagon_GD_PLT:
- FixupKind = Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL;
+ FixupKind = *Extended ? Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL_X
+ : Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL;
break;
case MCSymbolRefExpr::VK_Hexagon_LD_PLT:
- FixupKind = Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL;
+ FixupKind = *Extended ? Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL_X
+ : Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL;
break;
case MCSymbolRefExpr::VK_None:
FixupKind = *Extended ? Hexagon::fixup_Hexagon_B22_PCREL_X
@@ -467,8 +476,8 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
} else
switch (kind) {
case MCSymbolRefExpr::VK_None: {
- if (HexagonMCInstrInfo::s23_2_reloc(*MO.getExpr()))
- FixupKind = Hexagon::fixup_Hexagon_23_REG;
+ if (HexagonMCInstrInfo::s27_2_reloc(*MO.getExpr()))
+ FixupKind = Hexagon::fixup_Hexagon_27_REG;
else
if (MCID.mayStore() || MCID.mayLoad()) {
for (const MCPhysReg *ImpUses = MCID.getImplicitUses(); *ImpUses;
@@ -593,6 +602,12 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
case MCSymbolRefExpr::VK_Hexagon_LD_GOT:
FixupKind = Hexagon::fixup_Hexagon_LD_GOT_11_X;
break;
+ case MCSymbolRefExpr::VK_Hexagon_GD_PLT:
+ FixupKind = Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL_X;
+ break;
+ case MCSymbolRefExpr::VK_Hexagon_LD_PLT:
+ FixupKind = Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL_X;
+ break;
case MCSymbolRefExpr::VK_None:
FixupKind = Hexagon::fixup_Hexagon_11_X;
break;
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
index 14300edc7e1b..9fbe299d7d52 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
@@ -94,9 +94,9 @@ void HexagonMCExpr::setMustNotExtend(bool Val) {
}
bool HexagonMCExpr::mustNotExtend() const { return MustNotExtend; }
-bool HexagonMCExpr::s23_2_reloc() const { return S23_2_reloc; }
-void HexagonMCExpr::setS23_2_reloc(bool Val) {
- S23_2_reloc = Val;
+bool HexagonMCExpr::s27_2_reloc() const { return S27_2_reloc; }
+void HexagonMCExpr::setS27_2_reloc(bool Val) {
+ S27_2_reloc = Val;
}
bool HexagonMCExpr::classof(MCExpr const *E) {
@@ -104,7 +104,7 @@ bool HexagonMCExpr::classof(MCExpr const *E) {
}
HexagonMCExpr::HexagonMCExpr(MCExpr const *Expr)
- : Expr(Expr), MustNotExtend(false), MustExtend(false), S23_2_reloc(false),
+ : Expr(Expr), MustNotExtend(false), MustExtend(false), S27_2_reloc(false),
SignMismatch(false) {}
void HexagonMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
index bca40cfaf6f4..acfd996ccf82 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
@@ -29,8 +29,8 @@ public:
bool mustExtend() const;
void setMustNotExtend(bool Val = true);
bool mustNotExtend() const;
- void setS23_2_reloc(bool Val = true);
- bool s23_2_reloc() const;
+ void setS27_2_reloc(bool Val = true);
+ bool s27_2_reloc() const;
void setSignMismatch(bool Val = true);
bool signMismatch() const;
@@ -39,7 +39,7 @@ private:
MCExpr const *Expr;
bool MustNotExtend;
bool MustExtend;
- bool S23_2_reloc;
+ bool S27_2_reloc;
bool SignMismatch;
};
} // end namespace llvm
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
index 30a811a36406..5fe638a9996b 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
@@ -22,6 +22,49 @@
#include "llvm/MC/MCSubtargetInfo.h"
namespace llvm {
+
+Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
+ MCInst const &Inst)
+ : MCII(MCII), BundleCurrent(Inst.begin() +
+ HexagonMCInstrInfo::bundleInstructionsOffset),
+ BundleEnd(Inst.end()), DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {}
+
+Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
+ MCInst const &Inst, std::nullptr_t)
+ : MCII(MCII), BundleCurrent(Inst.end()), BundleEnd(Inst.end()),
+ DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {}
+
+Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() {
+ if (DuplexCurrent != DuplexEnd) {
+ ++DuplexCurrent;
+ if (DuplexCurrent == DuplexEnd) {
+ DuplexCurrent = BundleEnd;
+ DuplexEnd = BundleEnd;
+ }
+ return *this;
+ }
+ ++BundleCurrent;
+ if (BundleCurrent != BundleEnd) {
+ MCInst const &Inst = *BundleCurrent->getInst();
+ if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
+ DuplexCurrent = Inst.begin();
+ DuplexEnd = Inst.end();
+ }
+ }
+ return *this;
+}
+
+MCInst const &Hexagon::PacketIterator::operator*() const {
+ if (DuplexCurrent != DuplexEnd)
+ return *DuplexCurrent->getInst();
+ return *BundleCurrent->getInst();
+}
+
+bool Hexagon::PacketIterator::operator==(PacketIterator const &Other) const {
+ return BundleCurrent == Other.BundleCurrent && BundleEnd == Other.BundleEnd &&
+ DuplexCurrent == Other.DuplexCurrent && DuplexEnd == Other.DuplexEnd;
+}
+
void HexagonMCInstrInfo::addConstant(MCInst &MI, uint64_t Value,
MCContext &Context) {
MI.addOperand(MCOperand::createExpr(MCConstantExpr::create(Value, Context)));
@@ -41,6 +84,14 @@ void HexagonMCInstrInfo::addConstExtender(MCContext &Context,
MCB.addOperand(MCOperand::createInst(XMCI));
}
+iterator_range<Hexagon::PacketIterator>
+HexagonMCInstrInfo::bundleInstructions(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ assert(isBundle(MCI));
+ return make_range(Hexagon::PacketIterator(MCII, MCI),
+ Hexagon::PacketIterator(MCII, MCI, nullptr));
+}
+
iterator_range<MCInst::const_iterator>
HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) {
assert(isBundle(MCI));
@@ -292,7 +343,7 @@ int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII,
}
StringRef HexagonMCInstrInfo::getName(MCInstrInfo const &MCII,
- MCInst const &MCI) {
+ MCInst const &MCI) {
return MCII.getName(MCI.getOpcode());
}
@@ -339,25 +390,6 @@ unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
}
-int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
- MCInst const &MCI) {
- const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
-
- HexagonII::SubTarget Target = static_cast<HexagonII::SubTarget>(
- (F >> HexagonII::validSubTargetPos) & HexagonII::validSubTargetMask);
-
- switch (Target) {
- default:
- return Hexagon::ArchV4;
- case HexagonII::HasV5SubT:
- return Hexagon::ArchV5;
- case HexagonII::HasV55SubT:
- return Hexagon::ArchV55;
- case HexagonII::HasV60SubT:
- return Hexagon::ArchV60;
- }
-}
-
/// Return the slots this instruction can execute out of
unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
@@ -397,9 +429,8 @@ bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
- for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
- auto MI = I.getInst();
- if (HexagonMCInstrInfo::isDuplex(MCII, *MI))
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI)) {
+ if (HexagonMCInstrInfo::isDuplex(MCII, I))
return true;
}
@@ -410,13 +441,12 @@ bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
return extenderForIndex(MCB, Index) != nullptr;
}
-bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
+bool HexagonMCInstrInfo::hasImmExt( MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
- auto MI = I.getInst();
- if (isImmext(*MI))
+ if (isImmext(*I.getInst()))
return true;
}
@@ -737,16 +767,16 @@ bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) {
HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr);
return HExpr.mustNotExtend();
}
-void HexagonMCInstrInfo::setS23_2_reloc(MCExpr const &Expr, bool Val) {
+void HexagonMCInstrInfo::setS27_2_reloc(MCExpr const &Expr, bool Val) {
HexagonMCExpr &HExpr =
const_cast<HexagonMCExpr &>(*llvm::cast<HexagonMCExpr>(&Expr));
- HExpr.setS23_2_reloc(Val);
+ HExpr.setS27_2_reloc(Val);
}
-bool HexagonMCInstrInfo::s23_2_reloc(MCExpr const &Expr) {
+bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) {
HexagonMCExpr const *HExpr = llvm::dyn_cast<HexagonMCExpr>(&Expr);
if (!HExpr)
return false;
- return HExpr->s23_2_reloc();
+ return HExpr->s27_2_reloc();
}
void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) {
@@ -818,4 +848,4 @@ unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer,
return 0x1;
return 0;
}
-}
+} // namespace llvm
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
index 4d2df4d0eb69..ca44c3a11ba7 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
@@ -31,6 +31,25 @@ public:
DuplexCandidate(unsigned i, unsigned j, unsigned iClass)
: packetIndexI(i), packetIndexJ(j), iClass(iClass) {}
};
+namespace Hexagon {
+class PacketIterator {
+ MCInstrInfo const &MCII;
+ MCInst::const_iterator BundleCurrent;
+ MCInst::const_iterator BundleEnd;
+ MCInst::const_iterator DuplexCurrent;
+ MCInst::const_iterator DuplexEnd;
+
+public:
+ PacketIterator(MCInstrInfo const &MCII, MCInst const &Inst);
+ PacketIterator(MCInstrInfo const &MCII, MCInst const &Inst, std::nullptr_t);
+ PacketIterator &operator++();
+ MCInst const &operator*() const;
+ bool operator==(PacketIterator const &Other) const;
+ bool operator!=(PacketIterator const &Other) const {
+ return !(*this == Other);
+ }
+};
+} // namespace Hexagon
namespace HexagonMCInstrInfo {
size_t const innerLoopOffset = 0;
int64_t const innerLoopMask = 1 << innerLoopOffset;
@@ -54,6 +73,8 @@ void addConstExtender(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB,
MCInst const &MCI);
// Returns a iterator range of instructions in this bundle
+iterator_range<Hexagon::PacketIterator>
+bundleInstructions(MCInstrInfo const &MCII, MCInst const &MCI);
iterator_range<MCInst::const_iterator> bundleInstructions(MCInst const &MCI);
// Returns the number of instructions in the bundle
@@ -131,7 +152,6 @@ MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI);
unsigned short getNewValueOp2(MCInstrInfo const &MCII, MCInst const &MCI);
MCOperand const &getNewValueOperand2(MCInstrInfo const &MCII,
MCInst const &MCI);
-int getSubTarget(MCInstrInfo const &MCII, MCInst const &MCI);
// Return the Hexagon ISA class for the insn.
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
@@ -263,14 +283,14 @@ bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
// Replace the instructions inside MCB, represented by Candidate
void replaceDuplex(MCContext &Context, MCInst &MCI, DuplexCandidate Candidate);
-bool s23_2_reloc(MCExpr const &Expr);
+bool s27_2_reloc(MCExpr const &Expr);
// Marks a bundle as endloop0
void setInnerLoop(MCInst &MCI);
void setMemReorderDisabled(MCInst &MCI);
void setMemStoreReorderEnabled(MCInst &MCI);
void setMustExtend(MCExpr const &Expr, bool Val = true);
void setMustNotExtend(MCExpr const &Expr, bool Val = true);
-void setS23_2_reloc(MCExpr const &Expr, bool Val = true);
+void setS27_2_reloc(MCExpr const &Expr, bool Val = true);
// Marks a bundle as endloop1
void setOuterLoop(MCInst &MCI);
@@ -283,7 +303,7 @@ unsigned SubregisterBit(unsigned Consumer, unsigned Producer,
// Attempt to find and replace compound pairs
void tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCI);
-}
-}
+} // namespace HexagonMCInstrInfo
+} // namespace llvm
#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINSTRINFO_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
index eb303464555d..a5afa1daeb9e 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
@@ -205,64 +205,12 @@ static struct {
} jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
#define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0]))
-namespace {
-bool isDuplexAGroup(unsigned Opcode) {
- switch (Opcode) {
- case Hexagon::SA1_addi:
- case Hexagon::SA1_addrx:
- case Hexagon::SA1_addsp:
- case Hexagon::SA1_and1:
- case Hexagon::SA1_clrf:
- case Hexagon::SA1_clrfnew:
- case Hexagon::SA1_clrt:
- case Hexagon::SA1_clrtnew:
- case Hexagon::SA1_cmpeqi:
- case Hexagon::SA1_combine0i:
- case Hexagon::SA1_combine1i:
- case Hexagon::SA1_combine2i:
- case Hexagon::SA1_combine3i:
- case Hexagon::SA1_combinerz:
- case Hexagon::SA1_combinezr:
- case Hexagon::SA1_dec:
- case Hexagon::SA1_inc:
- case Hexagon::SA1_seti:
- case Hexagon::SA1_setin1:
- case Hexagon::SA1_sxtb:
- case Hexagon::SA1_sxth:
- case Hexagon::SA1_tfr:
- case Hexagon::SA1_zxtb:
- case Hexagon::SA1_zxth:
- return true;
- break;
- default:
- return false;
- }
-}
-
-unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
- unsigned Result = 0;
- unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
- if (Type == HexagonII::TypeDUPLEX) {
- unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode();
- unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode();
- Result += !isDuplexAGroup(subInst0Opcode);
- Result += !isDuplexAGroup(subInst1Opcode);
- } else
- Result +=
- Type != HexagonII::TypeALU32_2op && Type != HexagonII::TypeALU32_3op &&
- Type != HexagonII::TypeALU32_ADDI && Type != HexagonII::TypeS_2op &&
- Type != HexagonII::TypeS_3op && Type != HexagonII::TypeALU64 &&
- (Type != HexagonII::TypeM || HexagonMCInstrInfo::isFloat(MCII, ID));
- return Result;
-}
-} // namespace
-
/// Check that the packet is legal and enforce relative insn order.
bool HexagonShuffler::check() {
// Descriptive slot masks.
const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
slotThree = 0x8, // slotFirstJump = 0x8,
- slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
+ slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
// Highest slots for branches and stores used to keep their original order.
// unsigned slotJump = slotFirstJump;
unsigned slotLoadStore = slotFirstLoadStore;
@@ -271,18 +219,12 @@ bool HexagonShuffler::check() {
// Number of memory operations, loads, solo loads, stores, solo stores, single
// stores.
unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
- // Number of HVX loads, HVX stores.
- unsigned CVIloads = 0, CVIstores = 0;
- // Number of duplex insns, solo insns.
- unsigned duplex = 0, solo = 0;
- // Number of insns restricting other insns in the packet to A and X types,
- // which is neither A or X types.
- unsigned onlyAX = 0, neitherAnorX = 0;
+ // Number of duplex insns
+ unsigned duplex = 0;
// Number of insns restricting other insns in slot #1 to A type.
unsigned onlyAin1 = 0;
// Number of insns restricting any insn in slot #1, except A2_nop.
unsigned onlyNo1 = 0;
- unsigned xtypeFloat = 0;
unsigned pSlot3Cnt = 0;
unsigned nvstores = 0;
unsigned memops = 0;
@@ -295,13 +237,8 @@ bool HexagonShuffler::check() {
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const &ID = ISJ->getDesc();
- if (HexagonMCInstrInfo::isSolo(MCII, ID))
- solo++;
- else if (HexagonMCInstrInfo::isSoloAX(MCII, ID))
- onlyAX++;
- else if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
- onlyAin1++;
- neitherAnorX += countNeitherAnorX(MCII, ID);
+ if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
+ ++onlyAin1;
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
++pSlot3Cnt;
slot3ISJ = ISJ;
@@ -314,8 +251,6 @@ bool HexagonShuffler::check() {
case HexagonII::TypeS_2op:
case HexagonII::TypeS_3op:
case HexagonII::TypeALU64:
- if (HexagonMCInstrInfo::isFloat(MCII, ID))
- ++xtypeFloat;
break;
case HexagonII::TypeJ:
++jumps;
@@ -325,7 +260,6 @@ bool HexagonShuffler::check() {
++onlyNo1;
case HexagonII::TypeCVI_VM_LD:
case HexagonII::TypeCVI_VM_TMP_LD:
- ++CVIloads;
case HexagonII::TypeLD:
++loads;
++memory;
@@ -341,7 +275,6 @@ bool HexagonShuffler::check() {
++onlyNo1;
case HexagonII::TypeCVI_VM_ST:
case HexagonII::TypeCVI_VM_NEW_ST:
- ++CVIstores;
case HexagonII::TypeST:
++stores;
++memory;
@@ -403,15 +336,22 @@ bool HexagonShuffler::check() {
++jumps;
foundBranches.push_back(ISJ);
}
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) {
+ ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ foundBranches.push_back(ISJ);
+ }
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) {
+ ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ foundBranches.push_back(ISJ);
+ }
break;
}
}
}
// Check if the packet is legal.
- if ((load0 > 1 || store0 > 1 || CVIloads > 1 || CVIstores > 1) ||
- (duplex > 1 || (duplex && memory)) || (solo && size() > 1) ||
- (onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) {
+ if ((load0 > 1 || store0 > 1) ||
+ (duplex > 1 || (duplex && memory))) {
reportError(llvm::Twine("invalid instruction packet"));
return false;
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
index bd31c7be4c0a..10a959008f44 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
@@ -105,8 +105,8 @@ class HexagonInstr {
public:
HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
MCInstrInfo const &MCII, MCInst const *id,
- MCInst const *Extender, unsigned s, bool x = false)
- : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
+ MCInst const *Extender, unsigned s)
+ : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {};
MCInst const &getDesc() const { return *ID; };
diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp
index a71b161b24cc..5a394fe02f16 100644
--- a/lib/Target/Mips/Mips16HardFloat.cpp
+++ b/lib/Target/Mips/Mips16HardFloat.cpp
@@ -490,15 +490,14 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
// remove the use-soft-float attribute
//
static void removeUseSoftFloat(Function &F) {
- AttributeList A;
+ AttrBuilder B;
DEBUG(errs() << "removing -use-soft-float\n");
- A = A.addAttribute(F.getContext(), AttributeList::FunctionIndex,
- "use-soft-float", "false");
- F.removeAttributes(AttributeList::FunctionIndex, A);
+ B.addAttribute("use-soft-float", "false");
+ F.removeAttributes(AttributeList::FunctionIndex, B);
if (F.hasFnAttribute("use-soft-float")) {
DEBUG(errs() << "still has -use-soft-float\n");
}
- F.addAttributes(AttributeList::FunctionIndex, A);
+ F.addAttributes(AttributeList::FunctionIndex, B);
}
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 5645fdc24850..32661099b79d 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -1017,6 +1017,14 @@ namespace llvm {
SDValue
combineElementTruncationToVectorTruncation(SDNode *N,
DAGCombinerInfo &DCI) const;
+
+ bool supportsModuloShift(ISD::NodeType Inst,
+ EVT ReturnType) const override {
+ assert((Inst == ISD::SHL || Inst == ISD::SRA || Inst == ISD::SRL) &&
+ "Expect a shift instruction");
+ assert(isOperationLegal(Inst, ReturnType));
+ return ReturnType.isVector();
+ }
};
namespace PPC {
diff --git a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
index d286158f407d..f56b238f91e6 100644
--- a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
+++ b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
@@ -530,9 +530,10 @@ static Type *getCmpOpsType(const Instruction *I, unsigned VF = 1) {
if (CmpInst *CI = dyn_cast<CmpInst>(I->getOperand(0)))
OpTy = CI->getOperand(0)->getType();
else if (Instruction *LogicI = dyn_cast<Instruction>(I->getOperand(0)))
- if (CmpInst *CI0 = dyn_cast<CmpInst>(LogicI->getOperand(0)))
- if (isa<CmpInst>(LogicI->getOperand(1)))
- OpTy = CI0->getOperand(0)->getType();
+ if (LogicI->getNumOperands() == 2)
+ if (CmpInst *CI0 = dyn_cast<CmpInst>(LogicI->getOperand(0)))
+ if (isa<CmpInst>(LogicI->getOperand(1)))
+ OpTy = CI0->getOperand(0)->getType();
if (OpTy != nullptr) {
if (VF == 1) {
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index d2f650cf8f47..784c3a6557ff 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -170,6 +170,8 @@ def FeatureAES : SubtargetFeature<"aes", "HasAES", "true",
[FeatureSSE2]>;
def FeatureTBM : SubtargetFeature<"tbm", "HasTBM", "true",
"Enable TBM instructions">;
+def FeatureLWP : SubtargetFeature<"lwp", "HasLWP", "true",
+ "Enable LWP instructions">;
def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true",
"Support MOVBE instruction">;
def FeatureRDRAND : SubtargetFeature<"rdrnd", "HasRDRAND", "true",
@@ -691,6 +693,7 @@ def : Proc<"bdver1", [
FeatureLZCNT,
FeaturePOPCNT,
FeatureXSAVE,
+ FeatureLWP,
FeatureSlowSHLD,
FeatureLAHFSAHF
]>;
@@ -713,6 +716,7 @@ def : Proc<"bdver2", [
FeatureXSAVE,
FeatureBMI,
FeatureTBM,
+ FeatureLWP,
FeatureFMA,
FeatureSlowSHLD,
FeatureLAHFSAHF
@@ -737,6 +741,7 @@ def : Proc<"bdver3", [
FeatureXSAVE,
FeatureBMI,
FeatureTBM,
+ FeatureLWP,
FeatureFMA,
FeatureXSAVEOPT,
FeatureSlowSHLD,
@@ -763,6 +768,7 @@ def : Proc<"bdver4", [
FeatureBMI,
FeatureBMI2,
FeatureTBM,
+ FeatureLWP,
FeatureFMA,
FeatureXSAVEOPT,
FeatureSlowSHLD,
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index fd11b671dd9b..ebd179e786da 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -3181,6 +3181,15 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
bool Is64Bit = Subtarget->is64Bit();
bool IsWin64 = Subtarget->isCallingConvWin64(CC);
+ const CallInst *CI =
+ CLI.CS ? dyn_cast<CallInst>(CLI.CS->getInstruction()) : nullptr;
+ const Function *CalledFn = CI ? CI->getCalledFunction() : nullptr;
+
+ // Functions with no_caller_saved_registers that need special handling.
+ if ((CI && CI->hasFnAttr("no_caller_saved_registers")) ||
+ (CalledFn && CalledFn->hasFnAttribute("no_caller_saved_registers")))
+ return false;
+
// Handle only C, fastcc, and webkit_js calling conventions for now.
switch (CC) {
default: return false;
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 6092fd2bfd69..83542aaa013b 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -2180,6 +2180,12 @@ X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
MachineFunction &MF = DAG.getMachineFunction();
X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
+ // In some cases we need to disable registers from the default CSR list.
+ // For example, when they are used for argument passing.
+ bool ShouldDisableCalleeSavedRegister =
+ CallConv == CallingConv::X86_RegCall ||
+ MF.getFunction()->hasFnAttribute("no_caller_saved_registers");
+
if (CallConv == CallingConv::X86_INTR && !Outs.empty())
report_fatal_error("X86 interrupts may not return any value");
@@ -2201,7 +2207,7 @@ X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
assert(VA.isRegLoc() && "Can only return in registers!");
// Add the register to the CalleeSaveDisableRegs list.
- if (CallConv == CallingConv::X86_RegCall)
+ if (ShouldDisableCalleeSavedRegister)
MF.getRegInfo().disableCalleeSavedRegister(VA.getLocReg());
SDValue ValToCopy = OutVals[OutsIndex];
@@ -2280,7 +2286,7 @@ X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
"Expecting two registers after Pass64BitArgInRegs");
// Add the second register to the CalleeSaveDisableRegs list.
- if (CallConv == CallingConv::X86_RegCall)
+ if (ShouldDisableCalleeSavedRegister)
MF.getRegInfo().disableCalleeSavedRegister(RVLocs[I].getLocReg());
} else {
RegsToPass.push_back(std::make_pair(VA.getLocReg(), ValToCopy));
@@ -2340,7 +2346,7 @@ X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
DAG.getRegister(RetValReg, getPointerTy(DAG.getDataLayout())));
// Add the returned register to the CalleeSaveDisableRegs list.
- if (CallConv == CallingConv::X86_RegCall)
+ if (ShouldDisableCalleeSavedRegister)
MF.getRegInfo().disableCalleeSavedRegister(RetValReg);
}
@@ -2540,7 +2546,7 @@ SDValue X86TargetLowering::LowerCallResult(
// In some calling conventions we need to remove the used registers
// from the register mask.
- if (RegMask && CallConv == CallingConv::X86_RegCall) {
+ if (RegMask) {
for (MCSubRegIterator SubRegs(VA.getLocReg(), TRI, /*IncludeSelf=*/true);
SubRegs.isValid(); ++SubRegs)
RegMask[*SubRegs / 32] &= ~(1u << (*SubRegs % 32));
@@ -3237,7 +3243,8 @@ SDValue X86TargetLowering::LowerFormalArguments(
}
}
- if (CallConv == CallingConv::X86_RegCall) {
+ if (CallConv == CallingConv::X86_RegCall ||
+ Fn->hasFnAttribute("no_caller_saved_registers")) {
const MachineRegisterInfo &MRI = MF.getRegInfo();
for (const auto &Pair : make_range(MRI.livein_begin(), MRI.livein_end()))
MF.getRegInfo().disableCalleeSavedRegister(Pair.first);
@@ -3329,6 +3336,11 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
bool IsSibcall = false;
X86MachineFunctionInfo *X86Info = MF.getInfo<X86MachineFunctionInfo>();
auto Attr = MF.getFunction()->getFnAttribute("disable-tail-calls");
+ const CallInst *CI =
+ CLI.CS ? dyn_cast<CallInst>(CLI.CS->getInstruction()) : nullptr;
+ const Function *Fn = CI ? CI->getCalledFunction() : nullptr;
+ bool HasNCSR = (CI && CI->hasFnAttr("no_caller_saved_registers")) ||
+ (Fn && Fn->hasFnAttribute("no_caller_saved_registers"));
if (CallConv == CallingConv::X86_INTR)
report_fatal_error("X86 interrupts may not be called directly");
@@ -3741,7 +3753,11 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
RegsToPass[i].second.getValueType()));
// Add a register mask operand representing the call-preserved registers.
- const uint32_t *Mask = RegInfo->getCallPreservedMask(MF, CallConv);
+ // If HasNCSR is asserted (attribute NoCallerSavedRegisters exists) then we
+ // set X86_INTR calling convention because it has the same CSR mask
+ // (same preserved registers).
+ const uint32_t *Mask = RegInfo->getCallPreservedMask(
+ MF, HasNCSR ? (CallingConv::ID)CallingConv::X86_INTR : CallConv);
assert(Mask && "Missing call preserved mask for calling convention");
// If this is an invoke in a 32-bit function using a funclet-based
@@ -3764,7 +3780,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// In some calling conventions we need to remove the used physical registers
// from the reg mask.
- if (CallConv == CallingConv::X86_RegCall) {
+ if (CallConv == CallingConv::X86_RegCall || HasNCSR) {
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
// Allocate a new Reg Mask and copy Mask.
@@ -19044,8 +19060,7 @@ static SDValue getScalarMaskingNode(SDValue Op, SDValue Mask,
if (Op.getOpcode() == X86ISD::FSETCCM ||
Op.getOpcode() == X86ISD::FSETCCM_RND)
return DAG.getNode(ISD::AND, dl, VT, Op, IMask);
- if (Op.getOpcode() == X86ISD::VFPCLASS ||
- Op.getOpcode() == X86ISD::VFPCLASSS)
+ if (Op.getOpcode() == X86ISD::VFPCLASSS)
return DAG.getNode(ISD::OR, dl, VT, Op, IMask);
if (PreservedSrc.isUndef())
@@ -20284,16 +20299,17 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget &Subtarget,
SelectionDAG &DAG) {
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
- const IntrinsicData* IntrData = getIntrinsicWithChain(IntNo);
+ const IntrinsicData *IntrData = getIntrinsicWithChain(IntNo);
if (!IntrData) {
- if (IntNo == llvm::Intrinsic::x86_seh_ehregnode)
+ switch (IntNo) {
+ case llvm::Intrinsic::x86_seh_ehregnode:
return MarkEHRegistrationNode(Op, DAG);
- if (IntNo == llvm::Intrinsic::x86_seh_ehguard)
+ case llvm::Intrinsic::x86_seh_ehguard:
return MarkEHGuard(Op, DAG);
- if (IntNo == llvm::Intrinsic::x86_flags_read_u32 ||
- IntNo == llvm::Intrinsic::x86_flags_read_u64 ||
- IntNo == llvm::Intrinsic::x86_flags_write_u32 ||
- IntNo == llvm::Intrinsic::x86_flags_write_u64) {
+ case llvm::Intrinsic::x86_flags_read_u32:
+ case llvm::Intrinsic::x86_flags_read_u64:
+ case llvm::Intrinsic::x86_flags_write_u32:
+ case llvm::Intrinsic::x86_flags_write_u64: {
// We need a frame pointer because this will get lowered to a PUSH/POP
// sequence.
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
@@ -20302,6 +20318,20 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget &Subtarget,
// during ExpandISelPseudos in EmitInstrWithCustomInserter.
return SDValue();
}
+ case Intrinsic::x86_lwpins32:
+ case Intrinsic::x86_lwpins64: {
+ SDLoc dl(Op);
+ SDValue Chain = Op->getOperand(0);
+ SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
+ SDValue LwpIns =
+ DAG.getNode(X86ISD::LWPINS, dl, VTs, Chain, Op->getOperand(2),
+ Op->getOperand(3), Op->getOperand(4));
+ SDValue SetCC = getSETCC(X86::COND_B, LwpIns.getValue(0), dl, DAG);
+ SDValue Result = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i8, SetCC);
+ return DAG.getNode(ISD::MERGE_VALUES, dl, Op->getVTList(), Result,
+ LwpIns.getValue(1));
+ }
+ }
return SDValue();
}
@@ -24477,6 +24507,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::CVTP2UI_RND: return "X86ISD::CVTP2UI_RND";
case X86ISD::CVTS2SI_RND: return "X86ISD::CVTS2SI_RND";
case X86ISD::CVTS2UI_RND: return "X86ISD::CVTS2UI_RND";
+ case X86ISD::LWPINS: return "X86ISD::LWPINS";
}
return nullptr;
}
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 46dc587c637d..18106c2eb394 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -559,6 +559,9 @@ namespace llvm {
// Conversions between float and half-float.
CVTPS2PH, CVTPH2PS,
+ // LWP insert record.
+ LWPINS,
+
// Compare and swap.
LCMPXCHG_DAG = ISD::FIRST_TARGET_MEMORY_OPCODE,
LCMPXCHG8_DAG,
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 26444dd1f619..888daa275265 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -821,6 +821,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPSHLQrr, X86::VPSHLQmr, 0 },
{ X86::VPSHLWrr, X86::VPSHLWmr, 0 },
+ // LWP foldable instructions
+ { X86::LWPINS32rri, X86::LWPINS32rmi, 0 },
+ { X86::LWPINS64rri, X86::LWPINS64rmi, 0 },
+ { X86::LWPVAL32rri, X86::LWPVAL32rmi, 0 },
+ { X86::LWPVAL64rri, X86::LWPVAL64rmi, 0 },
+
// BMI/BMI2/LZCNT/POPCNT/TBM foldable instructions
{ X86::BEXTR32rr, X86::BEXTR32rm, 0 },
{ X86::BEXTR64rr, X86::BEXTR64rm, 0 },
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index ce0876498677..cdf7ce19cdc8 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -283,6 +283,11 @@ def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA,
def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+def X86lwpins : SDNode<"X86ISD::LWPINS",
+ SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>,
+ SDTCisVT<2, i32>, SDTCisVT<3, i32>]>,
+ [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>;
+
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
@@ -836,6 +841,7 @@ def HasFMA : Predicate<"Subtarget->hasFMA()">;
def HasFMA4 : Predicate<"Subtarget->hasFMA4()">;
def HasXOP : Predicate<"Subtarget->hasXOP()">;
def HasTBM : Predicate<"Subtarget->hasTBM()">;
+def HasLWP : Predicate<"Subtarget->hasLWP()">;
def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">;
def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">;
def HasF16C : Predicate<"Subtarget->hasF16C()">;
@@ -2444,6 +2450,59 @@ defm TZMSK : tbm_binary_intr<0x01, "tzmsk", MRM4r, MRM4m>;
} // HasTBM, EFLAGS
//===----------------------------------------------------------------------===//
+// Lightweight Profiling Instructions
+
+let Predicates = [HasLWP] in {
+
+def LLWPCB : I<0x12, MRM0r, (outs), (ins GR32:$src), "llwpcb\t$src",
+ [(int_x86_llwpcb GR32:$src)], IIC_LWP>,
+ XOP, XOP9, Requires<[Not64BitMode]>;
+def SLWPCB : I<0x12, MRM1r, (outs GR32:$dst), (ins), "slwpcb\t$dst",
+ [(set GR32:$dst, (int_x86_slwpcb))], IIC_LWP>,
+ XOP, XOP9, Requires<[Not64BitMode]>;
+
+def LLWPCB64 : I<0x12, MRM0r, (outs), (ins GR64:$src), "llwpcb\t$src",
+ [(int_x86_llwpcb GR64:$src)], IIC_LWP>,
+ XOP, XOP9, VEX_W, Requires<[In64BitMode]>;
+def SLWPCB64 : I<0x12, MRM1r, (outs GR64:$dst), (ins), "slwpcb\t$dst",
+ [(set GR64:$dst, (int_x86_slwpcb))], IIC_LWP>,
+ XOP, XOP9, VEX_W, Requires<[In64BitMode]>;
+
+multiclass lwpins_intr<RegisterClass RC> {
+ def rri : Ii32<0x12, MRM0r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl),
+ "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}",
+ [(set EFLAGS, (X86lwpins RC:$src0, GR32:$src1, imm:$cntl))]>,
+ XOP_4V, XOPA;
+ let mayLoad = 1 in
+ def rmi : Ii32<0x12, MRM0m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl),
+ "lwpins\t{$cntl, $src1, $src0|$src0, $src1, $cntl}",
+ [(set EFLAGS, (X86lwpins RC:$src0, (loadi32 addr:$src1), imm:$cntl))]>,
+ XOP_4V, XOPA;
+}
+
+let Defs = [EFLAGS] in {
+ defm LWPINS32 : lwpins_intr<GR32>;
+ defm LWPINS64 : lwpins_intr<GR64>, VEX_W;
+} // EFLAGS
+
+multiclass lwpval_intr<RegisterClass RC, Intrinsic Int> {
+ def rri : Ii32<0x12, MRM1r, (outs), (ins RC:$src0, GR32:$src1, i32imm:$cntl),
+ "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}",
+ [(Int RC:$src0, GR32:$src1, imm:$cntl)], IIC_LWP>,
+ XOP_4V, XOPA;
+ let mayLoad = 1 in
+ def rmi : Ii32<0x12, MRM1m, (outs), (ins RC:$src0, i32mem:$src1, i32imm:$cntl),
+ "lwpval\t{$cntl, $src1, $src0|$src0, $src1, $cntl}",
+ [(Int RC:$src0, (loadi32 addr:$src1), imm:$cntl)], IIC_LWP>,
+ XOP_4V, XOPA;
+}
+
+defm LWPVAL32 : lwpval_intr<GR32, int_x86_lwpval32>;
+defm LWPVAL64 : lwpval_intr<GR64, int_x86_lwpval64>, VEX_W;
+
+} // HasLWP
+
+//===----------------------------------------------------------------------===//
// MONITORX/MWAITX Instructions
//
let SchedRW = [ WriteSystem ] in {
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index 1f16f3c9a14d..cf2ceef8013a 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -276,7 +276,14 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
bool HasAVX512 = Subtarget.hasAVX512();
bool CallsEHReturn = MF->callsEHReturn();
- switch (MF->getFunction()->getCallingConv()) {
+ CallingConv::ID CC = MF->getFunction()->getCallingConv();
+
+ // If attribute NoCallerSavedRegisters exists then we set X86_INTR calling
+ // convention because it has the CSR list.
+ if (MF->getFunction()->hasFnAttribute("no_caller_saved_registers"))
+ CC = CallingConv::X86_INTR;
+
+ switch (CC) {
case CallingConv::GHC:
case CallingConv::HiPE:
return CSR_NoRegs_SaveList;
diff --git a/lib/Target/X86/X86Schedule.td b/lib/Target/X86/X86Schedule.td
index 7f7efd7cad3f..4eae6ca7abe3 100644
--- a/lib/Target/X86/X86Schedule.td
+++ b/lib/Target/X86/X86Schedule.td
@@ -497,6 +497,7 @@ def IIC_IN_RI : InstrItinClass;
def IIC_OUT_RR : InstrItinClass;
def IIC_OUT_IR : InstrItinClass;
def IIC_INS : InstrItinClass;
+def IIC_LWP : InstrItinClass;
def IIC_MOV_REG_DR : InstrItinClass;
def IIC_MOV_DR_REG : InstrItinClass;
def IIC_MOV_REG_CR : InstrItinClass;
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index 82ff436f7ebf..9ab751e2b002 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -265,6 +265,7 @@ void X86Subtarget::initializeEnvironment() {
HasFMA4 = false;
HasXOP = false;
HasTBM = false;
+ HasLWP = false;
HasMOVBE = false;
HasRDRAND = false;
HasF16C = false;
diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
index 8568cf04e7d2..de1514243aeb 100644
--- a/lib/Target/X86/X86Subtarget.h
+++ b/lib/Target/X86/X86Subtarget.h
@@ -124,6 +124,9 @@ protected:
/// Target has TBM instructions.
bool HasTBM;
+ /// Target has LWP instructions
+ bool HasLWP;
+
/// True if the processor has the MOVBE instruction.
bool HasMOVBE;
@@ -447,6 +450,7 @@ public:
bool hasAnyFMA() const { return hasFMA() || hasFMA4(); }
bool hasXOP() const { return HasXOP; }
bool hasTBM() const { return HasTBM; }
+ bool hasLWP() const { return HasLWP; }
bool hasMOVBE() const { return HasMOVBE; }
bool hasRDRAND() const { return HasRDRAND; }
bool hasF16C() const { return HasF16C; }
diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp
index bc14630584e5..500b26b3be17 100644
--- a/lib/Target/X86/X86WinEHState.cpp
+++ b/lib/Target/X86/X86WinEHState.cpp
@@ -412,7 +412,7 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
// Can't use musttail due to prototype mismatch, but we can use tail.
Call->setTailCall(true);
// Set inreg so we pass it in EAX.
- Call->addAttribute(1, Attribute::InReg);
+ Call->addParamAttr(0, Attribute::InReg);
Builder.CreateRet(Call);
return Trampoline;
}