aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-08 10:22:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-04-08 10:22:46 +0000
commit8a37c71e9d8855c91b9ef296ed389248f960bb52 (patch)
treeba53c9477fd985f645c0cfbacb5e9466f36dde9c /llvm/lib
parent5bcd187b307a70f29854eb0c5ccdf30ff3770fe1 (diff)
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp7
-rw-r--r--llvm/lib/DWARFLinker/DWARFLinker.cpp36
-rw-r--r--llvm/lib/DWARFLinker/DWARFStreamer.cpp5
-rw-r--r--llvm/lib/Object/ELFObjectFile.cpp7
-rw-r--r--llvm/lib/Support/AddressRanges.cpp70
-rw-r--r--llvm/lib/Support/RISCVISAInfo.cpp2
-rw-r--r--llvm/lib/Target/ARM/ARMFrameLowering.cpp28
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp3
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp2
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp121
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.h9
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.td9
-rw-r--r--llvm/lib/Target/Sparc/SparcTargetMachine.cpp7
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp3
14 files changed, 250 insertions, 59 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index eed3d820c120..d9cde609e599 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -21361,10 +21361,9 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) {
// the source vector. The high bits map to zero. We will use a zero vector
// as the 2nd source operand of the shuffle, so use the 1st element of
// that vector (mask value is number-of-elements) for the high bits.
- if (i % ZextRatio == 0)
- ShufMask[i] = Extract.getConstantOperandVal(1);
- else
- ShufMask[i] = NumMaskElts;
+ int Low = DAG.getDataLayout().isBigEndian() ? (ZextRatio - 1) : 0;
+ ShufMask[i] = (i % ZextRatio == Low) ? Extract.getConstantOperandVal(1)
+ : NumMaskElts;
}
// Undef elements of the build vector remain undef because we initialize
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index d302d61894fa..9f6e54377ede 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1659,7 +1659,7 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
OrigDwarf.getDWARFObj().getRangesSection(),
OrigDwarf.isLittleEndian(), AddressSize);
- std::optional<AddressRangeValuePair> CachedRange;
+ std::optional<std::pair<AddressRange, int64_t>> CachedRange;
DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
uint64_t UnitBaseAddress =
@@ -1687,9 +1687,9 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
}
if (!CachedRange ||
- !CachedRange->Range.contains(Range.StartAddress + BaseAddress))
- CachedRange = FunctionRanges.getRangeThatContains(Range.StartAddress +
- BaseAddress);
+ !CachedRange->first.contains(Range.StartAddress + BaseAddress))
+ CachedRange = FunctionRanges.getRangeValueThatContains(
+ Range.StartAddress + BaseAddress);
// All range entries should lie in the function range.
if (!CachedRange) {
@@ -1698,8 +1698,8 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
}
LinkedRanges.insert(
- {Range.StartAddress + BaseAddress + CachedRange->Value,
- Range.EndAddress + BaseAddress + CachedRange->Value});
+ {Range.StartAddress + BaseAddress + CachedRange->second,
+ Range.EndAddress + BaseAddress + CachedRange->second});
}
}
@@ -1802,7 +1802,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
// in NewRows.
std::vector<DWARFDebugLine::Row> Seq;
const auto &FunctionRanges = Unit.getFunctionRanges();
- std::optional<AddressRangeValuePair> CurrRange;
+ std::optional<std::pair<AddressRange, int64_t>> CurrRange;
// FIXME: This logic is meant to generate exactly the same output as
// Darwin's classic dsymutil. There is a nicer way to implement this
@@ -1821,13 +1821,13 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
// it is marked as end_sequence in the input (because in that
// case, the relocation offset is accurate and that entry won't
// serve as the start of another function).
- if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address) ||
- (Row.Address.Address == CurrRange->Range.end() && !Row.EndSequence)) {
+ if (!CurrRange || !CurrRange->first.contains(Row.Address.Address) ||
+ (Row.Address.Address == CurrRange->first.end() && !Row.EndSequence)) {
// We just stepped out of a known range. Insert a end_sequence
// corresponding to the end of the range.
uint64_t StopAddress =
- CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
- CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
+ CurrRange ? CurrRange->first.end() + CurrRange->second : -1ULL;
+ CurrRange = FunctionRanges.getRangeValueThatContains(Row.Address.Address);
if (!CurrRange) {
if (StopAddress != -1ULL) {
// Try harder by looking in the Address ranges map.
@@ -1836,9 +1836,9 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
// for now do as dsymutil.
// FIXME: Understand exactly what cases this addresses and
// potentially remove it along with the Ranges map.
- if (std::optional<AddressRangeValuePair> Range =
- Ranges.getRangeThatContains(Row.Address.Address))
- StopAddress = Row.Address.Address + (*Range).Value;
+ if (std::optional<std::pair<AddressRange, int64_t>> Range =
+ Ranges.getRangeValueThatContains(Row.Address.Address))
+ StopAddress = Row.Address.Address + (*Range).second;
}
}
if (StopAddress != -1ULL && !Seq.empty()) {
@@ -1863,7 +1863,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
continue;
// Relocate row address and add it to the current sequence.
- Row.Address.Address += CurrRange->Value;
+ Row.Address.Address += CurrRange->second;
Seq.emplace_back(Row);
if (Row.EndSequence)
@@ -2002,8 +2002,8 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
// the function entry point, thus we can't just lookup the address
// in the debug map. Use the AddressInfo's range map to see if the FDE
// describes something that we can relocate.
- std::optional<AddressRangeValuePair> Range =
- Ranges.getRangeThatContains(Loc);
+ std::optional<std::pair<AddressRange, int64_t>> Range =
+ Ranges.getRangeValueThatContains(Loc);
if (!Range) {
// The +4 is to account for the size of the InitialLength field itself.
InputOffset = EntryOffset + InitialLength + 4;
@@ -2032,7 +2032,7 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
// fields that will get reconstructed by emitFDE().
unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize,
- Loc + Range->Value,
+ Loc + Range->second,
FrameData.substr(InputOffset, FDERemainingBytes));
InputOffset += FDERemainingBytes;
}
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index ae79e8cb9066..5cad267fd845 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -402,9 +402,10 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
// Linked addresses might end up in a different order.
// Build linked address ranges.
AddressRanges LinkedRanges;
- for (const AddressRangeValuePair &Range : FunctionRanges)
+ for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
LinkedRanges.insert(
- {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
+ {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
+ FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
if (!FunctionRanges.empty())
emitDwarfDebugArangesTable(Unit, LinkedRanges);
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index ebc57bd04be7..c6d536188391 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -303,12 +303,7 @@ Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const {
std::optional<StringRef> Attr =
Attributes.getAttributeString(RISCVAttrs::ARCH);
if (Attr) {
- // Suppress version checking for experimental extensions to prevent erroring
- // when getting any unknown version of experimental extension.
- auto ParseResult = RISCVISAInfo::parseArchString(
- *Attr, /*EnableExperimentalExtension=*/true,
- /*ExperimentalExtensionVersionCheck=*/false,
- /*IgnoreUnknown=*/true);
+ auto ParseResult = RISCVISAInfo::parseNormalizedArchString(*Attr);
if (!ParseResult)
return ParseResult.takeError();
auto &ISAInfo = *ParseResult;
diff --git a/llvm/lib/Support/AddressRanges.cpp b/llvm/lib/Support/AddressRanges.cpp
new file mode 100644
index 000000000000..187d5be00dae
--- /dev/null
+++ b/llvm/lib/Support/AddressRanges.cpp
@@ -0,0 +1,70 @@
+//===- AddressRanges.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/AddressRanges.h"
+#include "llvm/ADT/STLExtras.h"
+#include <inttypes.h>
+
+using namespace llvm;
+
+AddressRanges::Collection::const_iterator
+AddressRanges::insert(AddressRange Range) {
+ if (Range.size() == 0)
+ return Ranges.end();
+
+ auto It = llvm::upper_bound(Ranges, Range);
+ auto It2 = It;
+ while (It2 != Ranges.end() && It2->start() <= Range.end())
+ ++It2;
+ if (It != It2) {
+ Range = {Range.start(), std::max(Range.end(), std::prev(It2)->end())};
+ It = Ranges.erase(It, It2);
+ }
+ if (It != Ranges.begin() && Range.start() <= std::prev(It)->end()) {
+ --It;
+ *It = {It->start(), std::max(It->end(), Range.end())};
+ return It;
+ }
+
+ return Ranges.insert(It, Range);
+}
+
+AddressRanges::Collection::const_iterator
+AddressRanges::find(uint64_t Addr) const {
+ auto It = std::partition_point(
+ Ranges.begin(), Ranges.end(),
+ [=](const AddressRange &R) { return R.start() <= Addr; });
+
+ if (It == Ranges.begin())
+ return Ranges.end();
+
+ --It;
+ if (Addr >= It->end())
+ return Ranges.end();
+
+ return It;
+}
+
+AddressRanges::Collection::const_iterator
+AddressRanges::find(AddressRange Range) const {
+ if (Range.size() == 0)
+ return Ranges.end();
+
+ auto It = std::partition_point(
+ Ranges.begin(), Ranges.end(),
+ [=](const AddressRange &R) { return R.start() <= Range.start(); });
+
+ if (It == Ranges.begin())
+ return Ranges.end();
+
+ --It;
+ if (Range.end() > It->end())
+ return Ranges.end();
+
+ return It;
+}
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index b14fe1358d1f..7cb1147d4265 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -1060,6 +1060,8 @@ std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
std::string ExtName = Ext.first;
if (ExtName == "i") // i is not recognized in clang -cc1
continue;
+ if (!isSupportedExtension(ExtName))
+ continue;
std::string Feature = isExperimentalExtension(ExtName)
? "+experimental-" + ExtName
: "+" + ExtName;
diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
index 5fa7068c89eb..724705c25e3a 100644
--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
@@ -357,6 +357,34 @@ static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI,
.setMIFlags(Flags);
break;
+ case ARM::t2STR_PRE:
+ if (MBBI->getOperand(0).getReg() == ARM::SP &&
+ MBBI->getOperand(2).getReg() == ARM::SP &&
+ MBBI->getOperand(3).getImm() == -4) {
+ unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
+ MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
+ .addImm(1ULL << Reg)
+ .addImm(/*Wide=*/1)
+ .setMIFlags(Flags);
+ } else {
+ report_fatal_error("No matching SEH Opcode for t2STR_PRE");
+ }
+ break;
+
+ case ARM::t2LDR_POST:
+ if (MBBI->getOperand(1).getReg() == ARM::SP &&
+ MBBI->getOperand(2).getReg() == ARM::SP &&
+ MBBI->getOperand(3).getImm() == 4) {
+ unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
+ MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
+ .addImm(1ULL << Reg)
+ .addImm(/*Wide=*/1)
+ .setMIFlags(Flags);
+ } else {
+ report_fatal_error("No matching SEH Opcode for t2LDR_POST");
+ }
+ break;
+
case ARM::t2LDMIA_RET:
case ARM::t2LDMIA_UPD:
case ARM::t2STMDB_UPD: {
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6eea169f8919..a1dc6a0cd2c1 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4540,6 +4540,9 @@ SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
assert(N->getOffset() == 0 && "unexpected offset in global node");
+ if (DAG.getTarget().useEmulatedTLS())
+ return LowerToTLSEmulatedModel(N, DAG);
+
TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
if (DAG.getMachineFunction().getFunction().getCallingConv() ==
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index fb22ddd91ba0..14c0e276a11b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -178,6 +178,8 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
default: break;
case SP::FBCOND:
case SP::FBCONDA:
+ case SP::FBCOND_V9:
+ case SP::FBCONDA_V9:
case SP::BPFCC:
case SP::BPFCCA:
case SP::BPFCCNT:
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index 63f662c41f93..a3a09a36f1dd 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -28,6 +28,10 @@ using namespace llvm;
#define GET_INSTRINFO_CTOR_DTOR
#include "SparcGenInstrInfo.inc"
+static cl::opt<unsigned> BPccDisplacementBits(
+ "sparc-bpcc-offset-bits", cl::Hidden, cl::init(19),
+ cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)"));
+
// Pin the vtable to this file.
void SparcInstrInfo::anchor() {}
@@ -73,11 +77,6 @@ unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
return 0;
}
-static bool IsIntegerCC(unsigned CC)
-{
- return (CC <= SPCC::ICC_VC);
-}
-
static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
{
switch(CC) {
@@ -155,9 +154,7 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
llvm_unreachable("Invalid cond code");
}
-static bool isUncondBranchOpcode(int Opc) {
- return Opc == SP::BA || Opc == SP::BPA;
-}
+static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; }
static bool isI32CondBranchOpcode(int Opc) {
return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA ||
@@ -169,7 +166,10 @@ static bool isI64CondBranchOpcode(int Opc) {
Opc == SP::BPXCCANT;
}
-static bool isFCondBranchOpcode(int Opc) { return Opc == SP::FBCOND; }
+static bool isFCondBranchOpcode(int Opc) {
+ return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 ||
+ Opc == SP::FBCONDA_V9;
+}
static bool isCondBranchOpcode(int Opc) {
return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) ||
@@ -193,6 +193,34 @@ static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
Target = LastInst->getOperand(0).getMBB();
}
+MachineBasicBlock *
+SparcInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ default:
+ llvm_unreachable("unexpected opcode!");
+ case SP::BA:
+ case SP::BCOND:
+ case SP::BCONDA:
+ case SP::FBCOND:
+ case SP::FBCONDA:
+ case SP::BPICC:
+ case SP::BPICCA:
+ case SP::BPICCNT:
+ case SP::BPICCANT:
+ case SP::BPXCC:
+ case SP::BPXCCA:
+ case SP::BPXCCNT:
+ case SP::BPXCCANT:
+ case SP::BPFCC:
+ case SP::BPFCCA:
+ case SP::BPFCCNT:
+ case SP::BPFCCANT:
+ case SP::FBCOND_V9:
+ case SP::FBCONDA_V9:
+ return MI.getOperand(0).getMBB();
+ }
+}
+
bool SparcInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
@@ -285,36 +313,37 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,
assert(TBB && "insertBranch must not be told to insert a fallthrough");
assert((Cond.size() <= 2) &&
"Sparc branch conditions should have at most two components!");
- assert(!BytesAdded && "code size not handled");
if (Cond.empty()) {
assert(!FBB && "Unconditional branch with multiple successors!");
- BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(TBB);
+ BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB);
+ if (BytesAdded)
+ *BytesAdded = 8;
return 1;
}
// Conditional branch
unsigned Opc = Cond[0].getImm();
unsigned CC = Cond[1].getImm();
+ BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
- if (IsIntegerCC(CC)) {
- BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
- } else {
- BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC);
- }
- if (!FBB)
+ if (!FBB) {
+ if (BytesAdded)
+ *BytesAdded = 8;
return 1;
+ }
- BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(FBB);
+ BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB);
+ if (BytesAdded)
+ *BytesAdded = 16;
return 2;
}
unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved) const {
- assert(!BytesRemoved && "code size not handled");
-
MachineBasicBlock::iterator I = MBB.end();
unsigned Count = 0;
+ int Removed = 0;
while (I != MBB.begin()) {
--I;
@@ -325,10 +354,14 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,
!isUncondBranchOpcode(I->getOpcode()))
break; // Not a branch
+ Removed += getInstSizeInBytes(*I);
I->eraseFromParent();
I = MBB.end();
++Count;
}
+
+ if (BytesRemoved)
+ *BytesRemoved = Removed;
return Count;
}
@@ -340,6 +373,37 @@ bool SparcInstrInfo::reverseBranchCondition(
return false;
}
+bool SparcInstrInfo::isBranchOffsetInRange(unsigned BranchOpc,
+ int64_t Offset) const {
+ assert((Offset & 0b11) == 0 && "Malformed branch offset");
+ switch (BranchOpc) {
+ case SP::BA:
+ case SP::BCOND:
+ case SP::BCONDA:
+ case SP::FBCOND:
+ case SP::FBCONDA:
+ return isIntN(22, Offset >> 2);
+
+ case SP::BPICC:
+ case SP::BPICCA:
+ case SP::BPICCNT:
+ case SP::BPICCANT:
+ case SP::BPXCC:
+ case SP::BPXCCA:
+ case SP::BPXCCNT:
+ case SP::BPXCCANT:
+ case SP::BPFCC:
+ case SP::BPFCCA:
+ case SP::BPFCCNT:
+ case SP::BPFCCANT:
+ case SP::FBCOND_V9:
+ case SP::FBCONDA_V9:
+ return isIntN(BPccDisplacementBits, Offset >> 2);
+ }
+
+ llvm_unreachable("Unknown branch instruction!");
+}
+
void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const DebugLoc &DL, MCRegister DestReg,
@@ -530,6 +594,23 @@ Register SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
return GlobalBaseReg;
}
+unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
+ unsigned Opcode = MI.getOpcode();
+
+ if (MI.isInlineAsm()) {
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const char *AsmStr = MI.getOperand(0).getSymbolName();
+ return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
+ }
+
+ // If the instruction has a delay slot, be conservative and also include
+ // it for sizing purposes. This is done so that the BranchRelaxation pass
+ // will not mistakenly mark out-of-range branches as in-range.
+ if (MI.hasDelaySlot())
+ return get(Opcode).getSize() * 2;
+ return get(Opcode).getSize();
+}
+
bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
switch (MI.getOpcode()) {
case TargetOpcode::LOAD_STACK_GUARD: {
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.h b/llvm/lib/Target/Sparc/SparcInstrInfo.h
index 39cf791c2173..7056d6babe17 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.h
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.h
@@ -64,6 +64,8 @@ public:
unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
+ MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
+
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
@@ -80,6 +82,9 @@ public:
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
+ /// Determine if the branch target is in range.
+ bool isBranchOffsetInRange(unsigned BranchOpc, int64_t Offset) const override;
+
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
bool KillSrc) const override;
@@ -99,6 +104,10 @@ public:
Register getGlobalBaseReg(MachineFunction *MF) const;
+ /// GetInstSize - Return the number of bytes of code the specified
+ /// instruction may be. This returns the maximum number of bytes.
+ unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
+
// Lower pseudo instructions after register allocation.
bool expandPostRAPseudo(MachineInstr &MI) const override;
};
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 2c45a7218d04..2e95bc10337a 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -850,15 +850,8 @@ class BranchPredictAlways<dag ins, string asmstr, list<dag> pattern>
: F2_3<0b001, 0, 1, (outs), ins, asmstr, pattern>;
}
-let cond = 8 in {
- // If we're compiling for v9, prefer BPA rather than BA
- // TODO: Disallow BA emission when FeatureV8Deprecated isn't enabled
- let Predicates = [HasV9], cc = 0b00 in
- def BPA : BranchPredictAlways<(ins bprtarget:$imm19),
- "ba %icc, $imm19", [(br bb:$imm19)]>;
-
+let cond = 8 in
def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>;
-}
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in {
diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
index 58faaafc29d6..1dbe5c563359 100644
--- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -32,6 +32,10 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() {
initializeSparcDAGToDAGISelPass(PR);
}
+static cl::opt<bool>
+ BranchRelaxation("sparc-enable-branch-relax", cl::Hidden, cl::init(true),
+ cl::desc("Relax out of range conditional branches"));
+
static std::string computeDataLayout(const Triple &T, bool is64Bit) {
// Sparc is typically big endian, but some are little.
std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E";
@@ -182,6 +186,9 @@ bool SparcPassConfig::addInstSelector() {
}
void SparcPassConfig::addPreEmitPass(){
+ if (BranchRelaxation)
+ addPass(&BranchRelaxationPassID);
+
addPass(createSparcDelaySlotFillerPass());
if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad())
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 31cdd2ee56b9..b2ed95b05e04 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -2930,7 +2930,8 @@ void llvm::copyRangeMetadata(const DataLayout &DL, const LoadInst &OldLI,
return;
unsigned BitWidth = DL.getPointerTypeSizeInBits(NewTy);
- if (!getConstantRangeFromMetadata(*N).contains(APInt(BitWidth, 0))) {
+ if (BitWidth == OldLI.getType()->getScalarSizeInBits() &&
+ !getConstantRangeFromMetadata(*N).contains(APInt(BitWidth, 0))) {
MDNode *NN = MDNode::get(OldLI.getContext(), std::nullopt);
NewLI.setMetadata(LLVMContext::MD_nonnull, NN);
}