aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp111
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp53
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp8
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp10
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp6
-rw-r--r--llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp1
-rw-r--r--llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp16
-rw-r--r--llvm/lib/CodeGen/RegisterCoalescer.cpp6
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp33
9 files changed, 149 insertions, 95 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 10df9c1..219bbc9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -20,6 +20,7 @@
#include "WinException.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -205,6 +206,17 @@ public:
};
} // namespace
+namespace callgraph {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+enum Flags : uint8_t {
+ None = 0,
+ IsIndirectTarget = 1u << 0,
+ HasDirectCallees = 1u << 1,
+ HasIndirectCallees = 1u << 2,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ HasIndirectCallees)
+};
+} // namespace callgraph
+
class llvm::AddrLabelMap {
MCContext &Context;
struct AddrLabelSymEntry {
@@ -1683,63 +1695,65 @@ void AsmPrinter::emitCallGraphSection(const MachineFunction &MF,
OutStreamer->pushSection();
OutStreamer->switchSection(FuncCGSection);
- // Emit format version number.
- OutStreamer->emitInt64(CallGraphSectionFormatVersion::V_0);
-
- // Emit function's self information, which is composed of:
- // 1) FunctionEntryPc
- // 2) FunctionKind: Whether the function is indirect target, and if so,
- // whether its type id is known.
- // 3) FunctionTypeId: Emit only when the function is an indirect target
- // and its type id is known.
-
- // Emit function entry pc.
const MCSymbol *FunctionSymbol = getFunctionBegin();
- OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());
-
+ const Function &F = MF.getFunction();
// If this function has external linkage or has its address taken and
// it is not a callback, then anything could call it.
- const Function &F = MF.getFunction();
bool IsIndirectTarget =
!F.hasLocalLinkage() || F.hasAddressTaken(nullptr,
/*IgnoreCallbackUses=*/true,
/*IgnoreAssumeLikeCalls=*/true,
/*IgnoreLLVMUsed=*/false);
- // FIXME: FunctionKind takes a few values but emitted as a 64-bit value.
- // Can be optimized to occupy 2 bits instead.
- // Emit function kind, and type id if available.
- if (!IsIndirectTarget) {
- OutStreamer->emitInt64(
- static_cast<uint64_t>(FunctionKind::NOT_INDIRECT_TARGET));
- } else {
- if (const auto *TypeId = extractNumericCGTypeId(F)) {
- OutStreamer->emitInt64(
- static_cast<uint64_t>(FunctionKind::INDIRECT_TARGET_KNOWN_TID));
- OutStreamer->emitInt64(TypeId->getZExtValue());
- } else {
- OutStreamer->emitInt64(
- static_cast<uint64_t>(FunctionKind::INDIRECT_TARGET_UNKNOWN_TID));
- }
- }
+ const auto &DirectCallees = FuncCGInfo.DirectCallees;
+ const auto &IndirectCalleeTypeIDs = FuncCGInfo.IndirectCalleeTypeIDs;
+
+ using namespace callgraph;
+ Flags CGFlags = Flags::None;
+ if (IsIndirectTarget)
+ CGFlags |= Flags::IsIndirectTarget;
+ if (DirectCallees.size() > 0)
+ CGFlags |= Flags::HasDirectCallees;
+ if (IndirectCalleeTypeIDs.size() > 0)
+ CGFlags |= Flags::HasIndirectCallees;
+
+ // Emit function's call graph information.
+ // 1) CallGraphSectionFormatVersion
+ // 2) Flags
+ // a. LSB bit 0 is set to 1 if the function is a potential indirect
+ // target.
+ // b. LSB bit 1 is set to 1 if there are direct callees.
+ // c. LSB bit 2 is set to 1 if there are indirect callees.
+ // d. Rest of the 5 bits in Flags are reserved for any future use.
+ // 3) Function entry PC.
+ // 4) FunctionTypeID if the function is indirect target and its type id
+ // is known, otherwise it is set to 0.
+ // 5) Number of unique direct callees, if at least one exists.
+ // 6) For each unique direct callee, the callee's PC.
+ // 7) Number of unique indirect target type IDs, if at least one exists.
+ // 8) Each unique indirect target type id.
+ OutStreamer->emitInt8(CallGraphSectionFormatVersion::V_0);
+ OutStreamer->emitInt8(static_cast<uint8_t>(CGFlags));
+ OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());
+ const auto *TypeId = extractNumericCGTypeId(F);
+ if (IsIndirectTarget && TypeId)
+ OutStreamer->emitInt64(TypeId->getZExtValue());
+ else
+ OutStreamer->emitInt64(0);
- // Emit callsite labels, where each element is a pair of type id and
- // indirect callsite pc.
- const auto &CallSiteLabels = FuncCGInfo.CallSiteLabels;
- OutStreamer->emitInt64(CallSiteLabels.size());
- for (const auto &[TypeId, Label] : CallSiteLabels) {
- OutStreamer->emitInt64(TypeId);
- OutStreamer->emitSymbolValue(Label, TM.getProgramPointerSize());
+ if (DirectCallees.size() > 0) {
+ OutStreamer->emitULEB128IntValue(DirectCallees.size());
+ for (const auto &CalleeSymbol : DirectCallees)
+ OutStreamer->emitSymbolValue(CalleeSymbol, TM.getProgramPointerSize());
+ FuncCGInfo.DirectCallees.clear();
}
- FuncCGInfo.CallSiteLabels.clear();
-
- const auto &DirectCallees = FuncCGInfo.DirectCallees;
- OutStreamer->emitInt64(DirectCallees.size());
- for (const auto &CalleeSymbol : DirectCallees) {
- OutStreamer->emitSymbolValue(CalleeSymbol, TM.getProgramPointerSize());
+ if (IndirectCalleeTypeIDs.size() > 0) {
+ OutStreamer->emitULEB128IntValue(IndirectCalleeTypeIDs.size());
+ for (const auto &CalleeTypeId : IndirectCalleeTypeIDs)
+ OutStreamer->emitInt64(CalleeTypeId);
+ FuncCGInfo.IndirectCalleeTypeIDs.clear();
}
- FuncCGInfo.DirectCallees.clear();
-
+ // End of emitting call graph section contents.
OutStreamer->popSection();
}
@@ -1877,8 +1891,7 @@ void AsmPrinter::handleCallsiteForCallgraph(
FunctionCallGraphInfo &FuncCGInfo,
const MachineFunction::CallSiteInfoMap &CallSitesInfoMap,
const MachineInstr &MI) {
- assert(MI.isCall() &&
- "Callsite labels are meant for call instructions only.");
+ assert(MI.isCall() && "This method is meant for call instructions only.");
const MachineOperand &CalleeOperand = MI.getOperand(0);
if (CalleeOperand.isGlobal() || CalleeOperand.isSymbol()) {
// Handle direct calls.
@@ -1903,10 +1916,8 @@ void AsmPrinter::handleCallsiteForCallgraph(
// Handle indirect callsite info.
// Only indirect calls have type identifiers set.
for (ConstantInt *CalleeTypeId : CallSiteInfo->second.CalleeTypeIds) {
- MCSymbol *S = MF->getContext().createTempSymbol();
- OutStreamer->emitLabel(S);
uint64_t CalleeTypeIdVal = CalleeTypeId->getZExtValue();
- FuncCGInfo.CallSiteLabels.emplace_back(CalleeTypeIdVal, S);
+ FuncCGInfo.IndirectCalleeTypeIDs.insert(CalleeTypeIdVal);
}
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 12d749c..e57ed24 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -569,40 +569,30 @@ void CodeViewDebug::emitCodeViewMagicVersion() {
OS.emitInt32(COFF::DEBUG_SECTION_MAGIC);
}
-static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
- switch (DWLang) {
- case dwarf::DW_LANG_C:
- case dwarf::DW_LANG_C89:
- case dwarf::DW_LANG_C99:
- case dwarf::DW_LANG_C11:
+static SourceLanguage
+MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName) {
+ switch (DWLName) {
+ case dwarf::DW_LNAME_C:
return SourceLanguage::C;
- case dwarf::DW_LANG_C_plus_plus:
- case dwarf::DW_LANG_C_plus_plus_03:
- case dwarf::DW_LANG_C_plus_plus_11:
- case dwarf::DW_LANG_C_plus_plus_14:
+ case dwarf::DW_LNAME_C_plus_plus:
return SourceLanguage::Cpp;
- case dwarf::DW_LANG_Fortran77:
- case dwarf::DW_LANG_Fortran90:
- case dwarf::DW_LANG_Fortran95:
- case dwarf::DW_LANG_Fortran03:
- case dwarf::DW_LANG_Fortran08:
+ case dwarf::DW_LNAME_Fortran:
return SourceLanguage::Fortran;
- case dwarf::DW_LANG_Pascal83:
+ case dwarf::DW_LNAME_Pascal:
return SourceLanguage::Pascal;
- case dwarf::DW_LANG_Cobol74:
- case dwarf::DW_LANG_Cobol85:
+ case dwarf::DW_LNAME_Cobol:
return SourceLanguage::Cobol;
- case dwarf::DW_LANG_Java:
+ case dwarf::DW_LNAME_Java:
return SourceLanguage::Java;
- case dwarf::DW_LANG_D:
+ case dwarf::DW_LNAME_D:
return SourceLanguage::D;
- case dwarf::DW_LANG_Swift:
+ case dwarf::DW_LNAME_Swift:
return SourceLanguage::Swift;
- case dwarf::DW_LANG_Rust:
+ case dwarf::DW_LNAME_Rust:
return SourceLanguage::Rust;
- case dwarf::DW_LANG_ObjC:
+ case dwarf::DW_LNAME_ObjC:
return SourceLanguage::ObjC;
- case dwarf::DW_LANG_ObjC_plus_plus:
+ case dwarf::DW_LNAME_ObjC_plus_plus:
return SourceLanguage::ObjCpp;
default:
// There's no CodeView representation for this language, and CV doesn't
@@ -612,6 +602,14 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
}
}
+static SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguage DWLang) {
+ auto MaybeLName = dwarf::toDW_LNAME(DWLang);
+ if (!MaybeLName)
+ return MapDWARFLanguageToCVLang(static_cast<dwarf::SourceLanguageName>(0));
+
+ return MapDWARFLanguageToCVLang(MaybeLName->first);
+}
+
void CodeViewDebug::beginModule(Module *M) {
// If COFF debug section is not available, skip any debug info related stuff.
if (!Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
@@ -633,8 +631,13 @@ void CodeViewDebug::beginModule(Module *M) {
Node = *CUs->operands().begin();
}
const auto *CU = cast<DICompileUnit>(Node);
+ DISourceLanguageName Lang = CU->getSourceLanguage();
CurrentSourceLanguage =
- MapDWLangToCVLang(CU->getSourceLanguage().getUnversionedName());
+ Lang.hasVersionedName()
+ ? MapDWARFLanguageToCVLang(
+ static_cast<dwarf::SourceLanguageName>(Lang.getName()))
+ : MapDWARFLanguageToCVLang(
+ static_cast<dwarf::SourceLanguage>(Lang.getName()));
if (!M->getCodeViewFlag() ||
CU->getEmissionKind() == DICompileUnit::NoDebug) {
Asm = nullptr;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index d751a7f..433877f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1039,8 +1039,12 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,
} else
NewCU.addString(Die, dwarf::DW_AT_producer, Producer);
- NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- DIUnit->getSourceLanguage().getUnversionedName());
+ if (auto Lang = DIUnit->getSourceLanguage(); Lang.hasVersionedName())
+ NewCU.addUInt(Die, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2,
+ Lang.getName());
+ else
+ NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ Lang.getName());
NewCU.addString(Die, dwarf::DW_AT_name, FN);
StringRef SysRoot = DIUnit->getSysRoot();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index bc0bb34..f0f0861 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -587,10 +587,12 @@ bool DwarfExpression::addExpression(
emitUnsigned(LeftShift);
emitOp(dwarf::DW_OP_shl);
}
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(RightShift);
- emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext ? dwarf::DW_OP_shra
- : dwarf::DW_OP_shr);
+ if (RightShift) {
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(RightShift);
+ emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext ? dwarf::DW_OP_shra
+ : dwarf::DW_OP_shr);
+ }
// The value is now at the top of the stack, so set the location to
// implicit so that we get a stack_value at the end.
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index eb73d01b..4320b1d 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -3194,7 +3194,7 @@ struct ExtAddrMode : public TargetLowering::AddrMode {
case ScaledRegField:
return ScaledReg;
case BaseOffsField:
- return ConstantInt::get(IntPtrTy, BaseOffs);
+ return ConstantInt::getSigned(IntPtrTy, BaseOffs);
}
}
@@ -6100,7 +6100,7 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// Add in the Base Offset if present.
if (AddrMode.BaseOffs) {
- Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs);
+ Value *V = ConstantInt::getSigned(IntPtrTy, AddrMode.BaseOffs);
if (ResultIndex) {
// We need to add this separately from the scale above to help with
// SDAG consecutive load/store merging.
@@ -6226,7 +6226,7 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// Add in the Base Offset if present.
if (AddrMode.BaseOffs) {
- Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs);
+ Value *V = ConstantInt::getSigned(IntPtrTy, AddrMode.BaseOffs);
if (Result)
Result = Builder.CreateAdd(Result, V, "sunkaddr");
else
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 906d62a3..b425b95 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1728,6 +1728,7 @@ static APFloat constantFoldFpUnary(const MachineInstr &MI,
Result.clearSign();
return Result;
}
+ case TargetOpcode::G_FPEXT:
case TargetOpcode::G_FPTRUNC: {
bool Unused;
LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 3f6813e..90c60d4 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -344,6 +344,22 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
Known = KnownBits::mul(Known, Known2);
break;
}
+ case TargetOpcode::G_UMULH: {
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::mulhu(Known, Known2);
+ break;
+ }
+ case TargetOpcode::G_SMULH: {
+ computeKnownBitsImpl(MI.getOperand(2).getReg(), Known, DemandedElts,
+ Depth + 1);
+ computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts,
+ Depth + 1);
+ Known = KnownBits::mulhs(Known, Known2);
+ break;
+ }
case TargetOpcode::G_SELECT: {
computeKnownBitsMin(MI.getOperand(2).getReg(), MI.getOperand(3).getReg(),
Known, DemandedElts, Depth + 1);
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index ebfea8e..e17a214 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -2051,6 +2051,12 @@ bool RegisterCoalescer::joinCopy(
}
if (CP.getNewRC()) {
+ if (RegClassInfo.getNumAllocatableRegs(CP.getNewRC()) == 0) {
+ LLVM_DEBUG(dbgs() << "\tNo " << TRI->getRegClassName(CP.getNewRC())
+ << "are available for allocation\n");
+ return false;
+ }
+
auto SrcRC = MRI->getRegClass(CP.getSrcReg());
auto DstRC = MRI->getRegClass(CP.getDstReg());
unsigned SrcIdx = CP.getSrcIdx();
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 5ffdc4e..b47274b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18870,27 +18870,38 @@ SDValue DAGCombiner::visitFPOW(SDNode *N) {
static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
const TargetLowering &TLI) {
- // We only do this if the target has legal ftrunc. Otherwise, we'd likely be
- // replacing casts with a libcall. We also must be allowed to ignore -0.0
- // because FTRUNC will return -0.0 for (-1.0, -0.0), but using integer
- // conversions would return +0.0.
+ // We can fold the fpto[us]i -> [us]itofp pattern into a single ftrunc.
+ // If NoSignedZerosFPMath is enabled, this is a direct replacement.
+ // Otherwise, for strict math, we must handle edge cases:
+ // 1. For unsigned conversions, use FABS to handle negative cases. Take -0.0
+ // as example, it first becomes integer 0, and is converted back to +0.0.
+ // FTRUNC on its own could produce -0.0.
+
// FIXME: We should be able to use node-level FMF here.
- // TODO: If strict math, should we use FABS (+ range check for signed cast)?
EVT VT = N->getValueType(0);
- if (!TLI.isOperationLegal(ISD::FTRUNC, VT) ||
- !DAG.getTarget().Options.NoSignedZerosFPMath)
+ if (!TLI.isOperationLegal(ISD::FTRUNC, VT))
return SDValue();
// fptosi/fptoui round towards zero, so converting from FP to integer and
// back is the same as an 'ftrunc': [us]itofp (fpto[us]i X) --> ftrunc X
SDValue N0 = N->getOperand(0);
if (N->getOpcode() == ISD::SINT_TO_FP && N0.getOpcode() == ISD::FP_TO_SINT &&
- N0.getOperand(0).getValueType() == VT)
- return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
+ N0.getOperand(0).getValueType() == VT) {
+ if (DAG.getTarget().Options.NoSignedZerosFPMath)
+ return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
+ }
if (N->getOpcode() == ISD::UINT_TO_FP && N0.getOpcode() == ISD::FP_TO_UINT &&
- N0.getOperand(0).getValueType() == VT)
- return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
+ N0.getOperand(0).getValueType() == VT) {
+ if (DAG.getTarget().Options.NoSignedZerosFPMath)
+ return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
+
+ // Strict math: use FABS to handle negative inputs correctly.
+ if (TLI.isFAbsFree(VT)) {
+ SDValue Abs = DAG.getNode(ISD::FABS, DL, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::FTRUNC, DL, VT, Abs);
+ }
+ }
return SDValue();
}