aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp16
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FastISel.cpp2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp9
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp4
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp3
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp21
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp60
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp15
9 files changed, 52 insertions, 80 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4f2eb1e..df353c4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10988,6 +10988,22 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
}
}
+ // fold (sra (xor (sra x, c1), -1), c2) -> (xor (sra x, c3), -1)
+ // This allows merging two arithmetic shifts even when there's a NOT in
+ // between.
+ SDValue X;
+ APInt C1;
+ if (N1C && sd_match(N0, m_OneUse(m_Not(
+ m_OneUse(m_Sra(m_Value(X), m_ConstInt(C1))))))) {
+ APInt C2 = N1C->getAPIntValue();
+ zeroExtendToMatch(C1, C2, 1 /* Overflow Bit */);
+ APInt Sum = C1 + C2;
+ unsigned ShiftSum = Sum.getLimitedValue(OpSizeInBits - 1);
+ SDValue NewShift = DAG.getNode(
+ ISD::SRA, DL, VT, X, DAG.getShiftAmountConstant(ShiftSum, VT, DL));
+ return DAG.getNOT(DL, NewShift, VT);
+ }
+
// fold (sra (shl X, m), (sub result_size, n))
// -> (sign_extend (trunc (shl X, (sub (sub result_size, n), m)))) for
// result_size - n != m.
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 507b2d6..5c84059 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1965,7 +1965,7 @@ Register FastISel::createResultReg(const TargetRegisterClass *RC) {
Register FastISel::constrainOperandRegClass(const MCInstrDesc &II, Register Op,
unsigned OpNum) {
if (Op.isVirtual()) {
- const TargetRegisterClass *RegClass = TII.getRegClass(II, OpNum, &TRI);
+ const TargetRegisterClass *RegClass = TII.getRegClass(II, OpNum);
if (!MRI.constrainRegClass(Op, RegClass)) {
// If it's not legal to COPY between the register classes, something
// has gone very wrong before we got here.
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index d84c3fb..72d0c44 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -125,7 +125,7 @@ void InstrEmitter::EmitCopyFromReg(SDValue Op, bool IsClone, Register SrcReg,
const TargetRegisterClass *RC = nullptr;
if (i + II.getNumDefs() < II.getNumOperands()) {
RC = TRI->getAllocatableClass(
- TII->getRegClass(II, i + II.getNumDefs(), TRI));
+ TII->getRegClass(II, i + II.getNumDefs()));
}
if (!UseRC)
UseRC = RC;
@@ -197,7 +197,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node,
// register instead of creating a new vreg.
Register VRBase;
const TargetRegisterClass *RC =
- TRI->getAllocatableClass(TII->getRegClass(II, i, TRI));
+ TRI->getAllocatableClass(TII->getRegClass(II, i));
// Always let the value type influence the used register class. The
// constraints on the instruction may be too lax to represent the value
// type correctly. For example, a 64-bit float (X86::FR64) can't live in
@@ -330,7 +330,7 @@ InstrEmitter::AddRegisterOperand(MachineInstrBuilder &MIB,
if (II) {
const TargetRegisterClass *OpRC = nullptr;
if (IIOpNum < II->getNumOperands())
- OpRC = TII->getRegClass(*II, IIOpNum, TRI);
+ OpRC = TII->getRegClass(*II, IIOpNum);
if (OpRC) {
unsigned MinNumRegs = MinRCSize;
@@ -409,8 +409,7 @@ void InstrEmitter::AddOperand(MachineInstrBuilder &MIB, SDValue Op,
Register VReg = R->getReg();
MVT OpVT = Op.getSimpleValueType();
const TargetRegisterClass *IIRC =
- II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum, TRI))
- : nullptr;
+ II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum)) : nullptr;
const TargetRegisterClass *OpRC =
TLI->isTypeLegal(OpVT)
? TLI->getRegClassFor(OpVT,
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index a0baf82..3ed84af 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -4842,7 +4842,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
? RTLIB::getSINCOS(VT)
: RTLIB::getSINCOSPI(VT);
- bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT);
+ bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results);
if (!Expanded) {
DAG.getContext()->emitError(Twine("no libcall available for ") +
Node->getOperationName(&DAG));
@@ -4940,7 +4940,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
: RTLIB::getFREXP(VT);
- bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT,
+ bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
/*CallRetResNo=*/0);
if (!Expanded)
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 29c4dac..58983cb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -1726,8 +1726,7 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
SmallVector<SDValue> Results;
- DAG.expandMultipleResultFPLibCall(LC, N, Results, N->getValueType(0),
- CallRetResNo);
+ DAG.expandMultipleResultFPLibCall(LC, N, Results, CallRetResNo);
for (auto [ResNo, Res] : enumerate(Results)) {
SDValue Lo, Hi;
GetPairElements(Res, Lo, Hi);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index f5a54497..c55e55d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -1268,30 +1268,25 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
return;
break;
-
+ case ISD::FSINCOS:
case ISD::FSINCOSPI: {
EVT VT = Node->getValueType(0);
- RTLIB::Libcall LC = RTLIB::getSINCOSPI(VT);
+ RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
+ ? RTLIB::getSINCOS(VT)
+ : RTLIB::getSINCOSPI(VT);
if (LC != RTLIB::UNKNOWN_LIBCALL &&
- DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT))
+ DAG.expandMultipleResultFPLibCall(LC, Node, Results))
return;
// TODO: Try to see if there's a narrower call available to use before
// scalarizing.
break;
}
- case ISD::FSINCOS: {
- // FIXME: Try to directly match vector case like fsincospi
- EVT VT = Node->getValueType(0).getVectorElementType();
- RTLIB::Libcall LC = RTLIB::getSINCOS(VT);
- if (DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT))
- return;
- break;
- }
case ISD::FMODF: {
- EVT VT = Node->getValueType(0).getVectorElementType();
+ EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = RTLIB::getMODF(VT);
- if (DAG.expandMultipleResultFPLibCall(LC, Node, Results, VT,
+ if (LC != RTLIB::UNKNOWN_LIBCALL &&
+ DAG.expandMultipleResultFPLibCall(LC, Node, Results,
/*CallRetResNo=*/0))
return;
break;
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index f70b6cd..12fc26d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -340,7 +340,7 @@ static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos,
unsigned Idx = RegDefPos.GetIdx();
const MCInstrDesc &Desc = TII->get(Opcode);
- const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx, TRI);
+ const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx);
assert(RC && "Not a valid register class");
RegClass = RC->getID();
// FIXME: Cost arbitrarily set to 1 because there doesn't seem to be a
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index b5d502b..f052669 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2514,56 +2514,14 @@ static bool canFoldStoreIntoLibCallOutputPointers(StoreSDNode *StoreNode,
bool SelectionDAG::expandMultipleResultFPLibCall(
RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl<SDValue> &Results,
- EVT CallVT, std::optional<unsigned> CallRetResNo) {
+ std::optional<unsigned> CallRetResNo) {
if (LC == RTLIB::UNKNOWN_LIBCALL)
return false;
- EVT VT = Node->getValueType(0);
-
- RTLIB::LibcallImpl Impl = TLI->getLibcallImpl(LC);
- if (Impl == RTLIB::Unsupported)
- return false;
-
- StringRef LCName = TLI->getLibcallImplName(Impl);
-
- // FIXME: This should not use TargetLibraryInfo. There should be
- // RTLIB::Libcall entries for each used vector type, and directly matched.
- auto getVecDesc = [&]() -> VecDesc const * {
- for (bool Masked : {false, true}) {
- if (VecDesc const *VD = getLibInfo().getVectorMappingInfo(
- LCName, VT.getVectorElementCount(), Masked)) {
- return VD;
- }
- }
- return nullptr;
- };
-
- // For vector types, we must find a vector mapping for the libcall.
- VecDesc const *VD = nullptr;
- if (VT.isVector() && !CallVT.isVector() && !(VD = getVecDesc()))
+ RTLIB::LibcallImpl LibcallImpl = TLI->getLibcallImpl(LC);
+ if (LibcallImpl == RTLIB::Unsupported)
return false;
- bool IsMasked = (VD && VD->isMasked()) ||
- RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(Impl);
-
- // This wrapper function exists because getVectorMappingInfo works in terms of
- // function names instead of RTLIB enums.
-
- // FIXME: If we used a vector mapping, this assumes the calling convention of
- // the vector function is the same as the scalar.
-
- StringRef Name = VD ? VD->getVectorFnName() : LCName;
-
- return expandMultipleResultFPLibCall(Name,
- TLI->getLibcallImplCallingConv(Impl),
- Node, Results, CallRetResNo, IsMasked);
-}
-
-// FIXME: This belongs in TargetLowering
-bool SelectionDAG::expandMultipleResultFPLibCall(
- StringRef Name, CallingConv::ID CC, SDNode *Node,
- SmallVectorImpl<SDValue> &Results, std::optional<unsigned> CallRetResNo,
- bool IsMasked) {
LLVMContext &Ctx = *getContext();
EVT VT = Node->getValueType(0);
unsigned NumResults = Node->getNumValues();
@@ -2624,8 +2582,8 @@ bool SelectionDAG::expandMultipleResultFPLibCall(
SDLoc DL(Node);
- // Pass the vector mask (if required).
- if (IsMasked) {
+ if (RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(LibcallImpl)) {
+ // Pass the vector mask (if required).
EVT MaskVT = TLI->getSetCCResultType(getDataLayout(), Ctx, VT);
SDValue Mask = getBoolConstant(true, DL, MaskVT, VT);
Args.emplace_back(Mask, MaskVT.getTypeForEVT(Ctx));
@@ -2636,10 +2594,12 @@ bool SelectionDAG::expandMultipleResultFPLibCall(
: Type::getVoidTy(Ctx);
SDValue InChain = StoresInChain ? StoresInChain : getEntryNode();
SDValue Callee =
- getExternalSymbol(Name.data(), TLI->getPointerTy(getDataLayout()));
+ getExternalSymbol(TLI->getLibcallImplName(LibcallImpl).data(),
+ TLI->getPointerTy(getDataLayout()));
TargetLowering::CallLoweringInfo CLI(*this);
- CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(CC, RetType, Callee,
- std::move(Args));
+ CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
+ TLI->getLibcallImplCallingConv(LibcallImpl), RetType, Callee,
+ std::move(Args));
auto [Call, CallChain] = TLI->LowerCallTo(CLI);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 6a9022d..9baf72b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9456,7 +9456,9 @@ bool SelectionDAGBuilder::visitStrNLenCall(const CallInst &I) {
bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
unsigned Opcode) {
// We already checked this call's prototype; verify it doesn't modify errno.
- if (!I.onlyReadsMemory())
+ // Do not perform optimizations for call sites that require strict
+ // floating-point semantics.
+ if (!I.onlyReadsMemory() || I.isStrictFP())
return false;
SDNodeFlags Flags;
@@ -9476,7 +9478,9 @@ bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
bool SelectionDAGBuilder::visitBinaryFloatCall(const CallInst &I,
unsigned Opcode) {
// We already checked this call's prototype; verify it doesn't modify errno.
- if (!I.onlyReadsMemory())
+ // Do not perform optimizations for call sites that require strict
+ // floating-point semantics.
+ if (!I.onlyReadsMemory() || I.isStrictFP())
return false;
SDNodeFlags Flags;
@@ -9509,11 +9513,10 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
// Check for well-known libc/libm calls. If the function is internal, it
// can't be a library call. Don't do the check if marked as nobuiltin for
- // some reason or the call site requires strict floating point semantics.
+ // some reason.
LibFunc Func;
- if (!I.isNoBuiltin() && !I.isStrictFP() && !F->hasLocalLinkage() &&
- F->hasName() && LibInfo->getLibFunc(*F, Func) &&
- LibInfo->hasOptimizedCodeGen(Func)) {
+ if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() &&
+ LibInfo->getLibFunc(*F, Func) && LibInfo->hasOptimizedCodeGen(Func)) {
switch (Func) {
default: break;
case LibFunc_bcmp: