[DAG] computeKnownFPClass - Add handling for AssertNoFPClass#190070
[DAG] computeKnownFPClass - Add handling for AssertNoFPClass#190070
Conversation
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
|
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-backend-x86 Author: Joao Victor Amorim Vieira (joaovam) ChangesResolves #189478 Adds code to handle AssertNoFPClass in computeKnownFPClass and adds IR test coverage for X86. Patch is 111.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/190070.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 3716de880cce3..cb4a0d6d11e8a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -92,8 +93,8 @@ static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) {
}
// Default null implementations of the callbacks.
-void SelectionDAG::DAGUpdateListener::NodeDeleted(SDNode*, SDNode*) {}
-void SelectionDAG::DAGUpdateListener::NodeUpdated(SDNode*) {}
+void SelectionDAG::DAGUpdateListener::NodeDeleted(SDNode *, SDNode *) {}
+void SelectionDAG::DAGUpdateListener::NodeUpdated(SDNode *) {}
void SelectionDAG::DAGUpdateListener::NodeInserted(SDNode *) {}
void SelectionDAG::DAGNodeDeletedListener::anchor() {}
@@ -101,13 +102,14 @@ void SelectionDAG::DAGNodeInsertedListener::anchor() {}
#define DEBUG_TYPE "selectiondag"
-static cl::opt<bool> EnableMemCpyDAGOpt("enable-memcpy-dag-opt",
- cl::Hidden, cl::init(true),
- cl::desc("Gang up loads and stores generated by inlining of memcpy"));
+static cl::opt<bool> EnableMemCpyDAGOpt(
+ "enable-memcpy-dag-opt", cl::Hidden, cl::init(true),
+ cl::desc("Gang up loads and stores generated by inlining of memcpy"));
-static cl::opt<int> MaxLdStGlue("ldstmemcpy-glue-max",
- cl::desc("Number limit for gluing ld/st of memcpy."),
- cl::Hidden, cl::init(0));
+static cl::opt<int>
+ MaxLdStGlue("ldstmemcpy-glue-max",
+ cl::desc("Number limit for gluing ld/st of memcpy."),
+ cl::Hidden, cl::init(0));
static cl::opt<unsigned>
MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192),
@@ -128,12 +130,11 @@ unsigned SelectionDAG::getHasPredecessorMaxSteps() { return MaxSteps; }
/// it returns true for things that are clearly not equal, like -0.0 and 0.0.
/// As such, this method can be used to do an exact bit-for-bit comparison of
/// two floating point values.
-bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const {
+bool ConstantFPSDNode::isExactlyValue(const APFloat &V) const {
return getValueAPF().bitwiseIsEqual(V);
}
-bool ConstantFPSDNode::isValueValidForType(EVT VT,
- const APFloat& Val) {
+bool ConstantFPSDNode::isValueValidForType(EVT VT, const APFloat &Val) {
assert(VT.isFloatingPoint() && "Can only convert between FP types");
// convert modifies in place, so make a copy.
@@ -189,7 +190,8 @@ bool ISD::isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly) {
return isConstantSplatVector(N, SplatVal) && SplatVal.isAllOnes();
}
- if (N->getOpcode() != ISD::BUILD_VECTOR) return false;
+ if (N->getOpcode() != ISD::BUILD_VECTOR)
+ return false;
unsigned i = 0, e = N->getNumOperands();
@@ -198,7 +200,8 @@ bool ISD::isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly) {
++i;
// Do not accept an all-undef vector.
- if (i == e) return false;
+ if (i == e)
+ return false;
// Do not accept build_vectors that aren't all constants or which have non-~0
// elements. We have to be a bit careful here, as the type of the constant
@@ -235,7 +238,8 @@ bool ISD::isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly) {
return isConstantSplatVector(N, SplatVal) && SplatVal.isZero();
}
- if (N->getOpcode() != ISD::BUILD_VECTOR) return false;
+ if (N->getOpcode() != ISD::BUILD_VECTOR)
+ return false;
bool IsAllUndef = true;
for (const SDValue &Op : N->op_values()) {
@@ -622,20 +626,20 @@ ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) {
// operation.
unsigned OldL = (Operation >> 2) & 1;
unsigned OldG = (Operation >> 1) & 1;
- return ISD::CondCode((Operation & ~6) | // Keep the N, U, E bits
- (OldL << 1) | // New G bit
- (OldG << 2)); // New L bit.
+ return ISD::CondCode((Operation & ~6) | // Keep the N, U, E bits
+ (OldL << 1) | // New G bit
+ (OldG << 2)); // New L bit.
}
static ISD::CondCode getSetCCInverseImpl(ISD::CondCode Op, bool isIntegerLike) {
unsigned Operation = Op;
if (isIntegerLike)
- Operation ^= 7; // Flip L, G, E bits, but not U.
+ Operation ^= 7; // Flip L, G, E bits, but not U.
else
- Operation ^= 15; // Flip all of the condition bits.
+ Operation ^= 15; // Flip all of the condition bits.
if (Operation > ISD::SETTRUE2)
- Operation &= ~8; // Don't let N and U bits get set.
+ Operation &= ~8; // Don't let N and U bits get set.
return ISD::CondCode(Operation);
}
@@ -654,17 +658,21 @@ ISD::CondCode ISD::GlobalISel::getSetCCInverse(ISD::CondCode Op,
/// does not depend on the sign of the input (setne and seteq).
static int isSignedOp(ISD::CondCode Opcode) {
switch (Opcode) {
- default: llvm_unreachable("Illegal integer setcc operation!");
+ default:
+ llvm_unreachable("Illegal integer setcc operation!");
case ISD::SETEQ:
- case ISD::SETNE: return 0;
+ case ISD::SETNE:
+ return 0;
case ISD::SETLT:
case ISD::SETLE:
case ISD::SETGT:
- case ISD::SETGE: return 1;
+ case ISD::SETGE:
+ return 1;
case ISD::SETULT:
case ISD::SETULE:
case ISD::SETUGT:
- case ISD::SETUGE: return 2;
+ case ISD::SETUGE:
+ return 2;
}
}
@@ -675,15 +683,15 @@ ISD::CondCode ISD::getSetCCOrOperation(ISD::CondCode Op1, ISD::CondCode Op2,
// Cannot fold a signed integer setcc with an unsigned integer setcc.
return ISD::SETCC_INVALID;
- unsigned Op = Op1 | Op2; // Combine all of the condition bits.
+ unsigned Op = Op1 | Op2; // Combine all of the condition bits.
// If the N and U bits get set, then the resultant comparison DOES suddenly
// care about orderedness, and it is true when ordered.
if (Op > ISD::SETTRUE2)
- Op &= ~16; // Clear the U bit if the N bit is set.
+ Op &= ~16; // Clear the U bit if the N bit is set.
// Canonicalize illegal integer setcc's.
- if (IsInteger && Op == ISD::SETUNE) // e.g. SETUGT | SETULT
+ if (IsInteger && Op == ISD::SETUNE) // e.g. SETUGT | SETULT
Op = ISD::SETNE;
return ISD::CondCode(Op);
@@ -702,12 +710,21 @@ ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2,
// Canonicalize illegal integer setcc's.
if (IsInteger) {
switch (Result) {
- default: break;
- case ISD::SETUO : Result = ISD::SETFALSE; break; // SETUGT & SETULT
- case ISD::SETOEQ: // SETEQ & SETU[LG]E
- case ISD::SETUEQ: Result = ISD::SETEQ ; break; // SETUGE & SETULE
- case ISD::SETOLT: Result = ISD::SETULT ; break; // SETULT & SETNE
- case ISD::SETOGT: Result = ISD::SETUGT ; break; // SETUGT & SETNE
+ default:
+ break;
+ case ISD::SETUO:
+ Result = ISD::SETFALSE;
+ break; // SETUGT & SETULT
+ case ISD::SETOEQ: // SETEQ & SETU[LG]E
+ case ISD::SETUEQ:
+ Result = ISD::SETEQ;
+ break; // SETUGE & SETULE
+ case ISD::SETOLT:
+ Result = ISD::SETULT;
+ break; // SETULT & SETNE
+ case ISD::SETOGT:
+ Result = ISD::SETUGT;
+ break; // SETUGT & SETNE
}
}
@@ -719,7 +736,7 @@ ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2,
//===----------------------------------------------------------------------===//
/// AddNodeIDOpcode - Add the node opcode to the NodeID data.
-static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) {
+static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) {
ID.AddInteger(OpC);
}
@@ -730,8 +747,7 @@ static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) {
}
/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
-static void AddNodeIDOperands(FoldingSetNodeID &ID,
- ArrayRef<SDValue> Ops) {
+static void AddNodeIDOperands(FoldingSetNodeID &ID, ArrayRef<SDValue> Ops) {
for (const auto &Op : Ops) {
ID.AddPointer(Op.getNode());
ID.AddInteger(Op.getResNo());
@@ -739,16 +755,15 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID,
}
/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
-static void AddNodeIDOperands(FoldingSetNodeID &ID,
- ArrayRef<SDUse> Ops) {
+static void AddNodeIDOperands(FoldingSetNodeID &ID, ArrayRef<SDUse> Ops) {
for (const auto &Op : Ops) {
ID.AddPointer(Op.getNode());
ID.AddInteger(Op.getResNo());
}
}
-static void AddNodeIDNode(FoldingSetNodeID &ID, unsigned OpC,
- SDVTList VTList, ArrayRef<SDValue> OpList) {
+static void AddNodeIDNode(FoldingSetNodeID &ID, unsigned OpC, SDVTList VTList,
+ ArrayRef<SDValue> OpList) {
AddNodeIDOpcode(ID, OpC);
AddNodeIDValueTypes(ID, VTList);
AddNodeIDOperands(ID, OpList);
@@ -761,7 +776,8 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
case ISD::ExternalSymbol:
case ISD::MCSymbol:
llvm_unreachable("Should only be used on nodes with operands");
- default: break; // Normal nodes don't need extra info.
+ default:
+ break; // Normal nodes don't need extra info.
case ISD::TargetConstant:
case ISD::Constant: {
const ConstantSDNode *C = cast<ConstantSDNode>(N);
@@ -1021,10 +1037,11 @@ static bool doNotCSE(SDNode *N) {
return true; // Never CSE anything that produces a glue result.
switch (N->getOpcode()) {
- default: break;
+ default:
+ break;
case ISD::HANDLENODE:
case ISD::EH_LABEL:
- return true; // Never CSE these nodes.
+ return true; // Never CSE these nodes.
}
// Check that remaining values produced are not flags.
@@ -1042,7 +1059,7 @@ void SelectionDAG::RemoveDeadNodes() {
// to the root node, preventing it from being deleted.
HandleSDNode Dummy(getRoot());
- SmallVector<SDNode*, 128> DeadNodes;
+ SmallVector<SDNode *, 128> DeadNodes;
// Add all obviously-dead nodes to the DeadNodes worklist.
for (SDNode &Node : allnodes())
@@ -1077,7 +1094,7 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes) {
// Next, brutally remove the operand list. This is safe to do, as there are
// no cycles in the graph.
- for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
+ for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E;) {
SDUse &Use = *I++;
SDNode *Operand = Use.getNode();
Use.set(SDValue());
@@ -1091,8 +1108,8 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes) {
}
}
-void SelectionDAG::RemoveDeadNode(SDNode *N){
- SmallVector<SDNode*, 16> DeadNodes(1, N);
+void SelectionDAG::RemoveDeadNode(SDNode *N) {
+ SmallVector<SDNode *, 16> DeadNodes(1, N);
// Create a dummy node that adds a reference to the root node, preventing
// it from being deleted. (This matters if the root is an operand of the
@@ -1137,7 +1154,7 @@ void SDDbgInfo::erase(const SDNode *Node) {
DbgValMapType::iterator I = DbgValMap.find(Node);
if (I == DbgValMap.end())
return;
- for (auto &Val: I->second)
+ for (auto &Val : I->second)
Val->setIsInvalidated();
DbgValMap.erase(I);
}
@@ -1239,7 +1256,8 @@ void SelectionDAG::InsertNode(SDNode *N) {
bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
bool Erased = false;
switch (N->getOpcode()) {
- case ISD::HANDLENODE: return false; // noop.
+ case ISD::HANDLENODE:
+ return false; // noop.
case ISD::CONDCODE:
assert(CondCodeNodes[cast<CondCodeSDNode>(N)->get()] &&
"Cond code doesn't exist!");
@@ -1281,7 +1299,7 @@ bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
// Verify that the node was actually in one of the CSE maps, unless it has a
// glue result (which cannot be CSE'd) or is one of the special cases that are
// not subject to CSE.
- if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Glue &&
+ if (!Erased && N->getValueType(N->getNumValues() - 1) != MVT::Glue &&
!N->isMachineOpcode() && !doNotCSE(N)) {
N->dump(this);
dbgs() << "\n";
@@ -1295,8 +1313,7 @@ bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
/// maps and modified in place. Add it back to the CSE maps, unless an identical
/// node already exists, in which case transfer all its users to the existing
/// node. This transfer can potentially trigger recursive merging.
-void
-SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) {
+void SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) {
// For node types that aren't CSE'd, just act as if no identical node
// already exists.
if (!doNotCSE(N)) {
@@ -1332,7 +1349,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op,
if (doNotCSE(N))
return nullptr;
- SDValue Ops[] = { Op };
+ SDValue Ops[] = {Op};
FoldingSetNodeID ID;
AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
AddNodeIDCustom(ID, N);
@@ -1346,13 +1363,12 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op,
/// were replaced with those specified. If this node is never memoized,
/// return null, otherwise return a pointer to the slot it would take. If a
/// node already exists with these operands, the slot will be non-null.
-SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
- SDValue Op1, SDValue Op2,
+SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2,
void *&InsertPos) {
if (doNotCSE(N))
return nullptr;
- SDValue Ops[] = { Op1, Op2 };
+ SDValue Ops[] = {Op1, Op2};
FoldingSetNodeID ID;
AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
AddNodeIDCustom(ID, N);
@@ -1444,7 +1460,8 @@ SDNode *SelectionDAG::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
SDNode *N = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
if (N) {
switch (N->getOpcode()) {
- default: break;
+ default:
+ break;
case ISD::Constant:
case ISD::ConstantFP:
llvm_unreachable("Querying for Constant and ConstantFP nodes requires "
@@ -1521,21 +1538,18 @@ SelectionDAG::getStrictFPExtendOrRound(SDValue Op, SDValue Chain,
}
SDValue SelectionDAG::getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
- return VT.bitsGT(Op.getValueType()) ?
- getNode(ISD::ANY_EXTEND, DL, VT, Op) :
- getNode(ISD::TRUNCATE, DL, VT, Op);
+ return VT.bitsGT(Op.getValueType()) ? getNode(ISD::ANY_EXTEND, DL, VT, Op)
+ : getNode(ISD::TRUNCATE, DL, VT, Op);
}
SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
- return VT.bitsGT(Op.getValueType()) ?
- getNode(ISD::SIGN_EXTEND, DL, VT, Op) :
- getNode(ISD::TRUNCATE, DL, VT, Op);
+ return VT.bitsGT(Op.getValueType()) ? getNode(ISD::SIGN_EXTEND, DL, VT, Op)
+ : getNode(ISD::TRUNCATE, DL, VT, Op);
}
SDValue SelectionDAG::getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
- return VT.bitsGT(Op.getValueType()) ?
- getNode(ISD::ZERO_EXTEND, DL, VT, Op) :
- getNode(ISD::TRUNCATE, DL, VT, Op);
+ return VT.bitsGT(Op.getValueType()) ? getNode(ISD::ZERO_EXTEND, DL, VT, Op)
+ : getNode(ISD::TRUNCATE, DL, VT, Op);
}
SDValue SelectionDAG::getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL,
@@ -1554,7 +1568,7 @@ SDValue SelectionDAG::getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL,
}
SDValue SelectionDAG::getBitcastedSExtOrTrunc(SDValue Op, const SDLoc &DL,
- EVT VT) {
+ EVT VT) {
assert(!VT.isVector());
auto Type = Op.getValueType();
SDValue DestOp;
@@ -1569,7 +1583,7 @@ SDValue SelectionDAG::getBitcastedSExtOrTrunc(SDValue Op, const SDLoc &DL,
}
SDValue SelectionDAG::getBitcastedZExtOrTrunc(SDValue Op, const SDLoc &DL,
- EVT VT) {
+ EVT VT) {
assert(!VT.isVector());
auto Type = Op.getValueType();
SDValue DestOp;
@@ -1747,8 +1761,7 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, const SDLoc &DL,
unsigned ViaEltSizeInBits = ViaEltVT.getSizeInBits();
// For scalable vectors, try to use a SPLAT_VECTOR_PARTS node.
- if (VT.isScalableVector() ||
- TLI->isOperationLegal(ISD::SPLAT_VECTOR, VT)) {
+ if (VT.isScalableVector() || TLI->isOperationLegal(ISD::SPLAT_VECTOR, VT)) {
assert(EltVT.getSizeInBits() % ViaEltSizeInBits == 0 &&
"Can only handle an even split!");
unsigned Parts = EltVT.getSizeInBits() / ViaEltSizeInBits;
@@ -1951,7 +1964,7 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, const SDLoc &DL,
auto *N = newSDNode<GlobalAddressSDNode>(
Opc, DL.getIROrder(), DL.getDebugLoc(), GV, VTs, Offset, TargetFlags);
CSEMap.InsertNode(N, IP);
- InsertNode(N);
+ InsertNode(N);
return SDValue(N, 0);
}
@@ -2084,14 +2097,15 @@ SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
}
SDValue SelectionDAG::getValueType(EVT VT) {
- if (VT.isSimple() && (unsigned)VT.getSimpleVT().SimpleTy >=
- ValueTypeNodes.size())
- ValueTypeNodes.resize(VT.getSimpleVT().SimpleTy+1);
+ if (VT.isSimple() &&
+ (unsigned)VT.getSimpleVT().SimpleTy >= ValueTypeNodes.size())
+ ValueTypeNodes.resize(VT.getSimpleVT().SimpleTy + 1);
- SDNode *&N = VT.isExtended() ?
- ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT.getSimpleVT().SimpleTy];
+ SDNode *&N = VT.isExtended() ? ExtendedValueTypeNodes[VT]
+ : ValueTypeNodes[VT.getSimpleVT().SimpleTy];
- if (N) return SDValue(N, 0);
+ if (N)
+ return SDValue(N, 0);
N = newSDNode<VTSDNode>(VT);
InsertNode(N);
return SDValue(N, 0);
@@ -2099,7 +2113,8 @@ SDValue SelectionDAG::getValueType(EVT VT) {
SDValue SelectionDAG::getExternalSymbol(const char *Sym, EVT VT) {
SDNode *&N = ExternalSymbols[Sym];
- if (N) return SDValue(N, 0);
+ if (N)
+ return SDValue(N, 0);
N = newSDNode<ExternalSymbolSDNode>(false, Sym, 0, getVTList(VT));
InsertNode(N);
return SDValue(N, 0);
@@ -2123,7 +2138,8 @@ SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, EVT VT,
unsigned TargetFlags) {
SDNode *&N =
TargetExternalSymbols[std::pair<std::string, unsigned>(Sym, TargetFlags)];
- if (N) return SDValue(N, 0);
+ if (N)
+ return SDValue(N, 0);
N = newSDNode<ExternalSymbolSDNode>(true, Sym, TargetFlags, getVTList(VT));
InsertNode(N);
return SDValue(N, 0);
@@ -2137,7 +2153,7 @@ SDValue SelectionDAG::getTargetExternalSymbol(RTLIB::LibcallImpl Libcall,
SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) {
if ((unsigned)Cond >= CondCodeNodes.size())
- CondCodeNodes.resize(Cond+1);
+ CondCodeNodes.resize(Cond + 1);
if (!CondCodeNodes[Cond]) {
auto *N = newSDNode<CondCodeSDNode>(Cond);
@@ -2236,9 +2252,9 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
// Validate that all indices in Mask are within the range of the elements
// input to the shuffle.
int NElts = Mask.size();
- assert(llvm::all_of(Mask,
- [&](int M) { return M < (NElts * 2) && M >= -1; }) &&
- "Index out of range");
+ assert(
+ llvm::all_of(Mask, [&](int M) { return M < (NElts * 2) && M >= -1; }) &&
+ "Index out of range");
// Copy the mask so we can do any needed cleanup.
SmallVector<int, 8> MaskVec(Mask);
@@ -2247,7 +2263,8 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
if (N1 == N2) {
N2 = getUNDEF(VT);
for (int i = 0; i != NElts; ++i)
- if (MaskVec[i] >= NElts) MaskVec[i] -= NElts;
+ if (MaskVec[i] >= NElts)
+ MaskVec[i] -= NElts;
}
// Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask.
@@ -2315,8 +2332,10 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
// If Identity s...
[truncated]
|
6b2f74e to
93e3964
Compare
…computeUnrollCount()` (llvm#185979) We currently set `UP.Count` to `TripCount` and `MaxTripCount` prior to full and upper bound unrolling, respectively. This was likely done to ensure that calls to `UCE.getUnrolledLoopSize(UP)` use the appropriate trip count. However, we can use `UCE.getUnrolledLoopSize(UP, FullUnrollTripCount)` instead. To prevent unintentional unrolling, we set `UP.Count = 0` when early-exiting `computeUnrollCount()`. (Note: this does not occur [here](https://github.com/llvm/llvm-project/blob/eb687fb10613573b5d60dfbbb146e15f07809d82/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L1190-L1198). This seems like a bug.) We only perform early exits when evaluating runtime unrolling. At that point, [we know `TripCount` is false](https://github.com/justinfargnoli/llvm-project/blob/3fb31e7b06f6f6d08c7310506a2f363d198a6790/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L1157-L1158), and thus we could not have leaked `TripCount`. However, we [could've leaked `MaxTripCount`](https://github.com/llvm/llvm-project/blob/eb687fb10613573b5d60dfbbb146e15f07809d82/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L1102-L1110). It seems like: https://github.com/llvm/llvm-project/blob/eb687fb10613573b5d60dfbbb146e15f07809d82/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L1181-L1188 was supposed to handle this case. However: - It uses `<` instead of `<=`. This breaks the existing convention [[1]](https://github.com/llvm/llvm-project/blob/eb687fb10613573b5d60dfbbb146e15f07809d82/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L869) [[2]](https://github.com/llvm/llvm-project/blob/eb687fb10613573b5d60dfbbb146e15f07809d82/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L1103) for how `UP.MaxUpperBound` is treated. - It's ignored when a target sets `UP.Force = true`. Thus: - When `UP.Force == false`, we leak `MaxTripCount` into runtime unrolling when `MaxTripCount && (UP.UpperBound || MaxOrZero) && MaxTripCount == UP.MaxUpperBound` - When `UP.Force == true`, we leak `MaxTripCount` into runtime unrolling when `MaxTripCount && (UP.UpperBound || MaxOrZero) && MaxTripCount <= UP.MaxUpperBound`. This PR: - Uses `UCE.getUnrolledLoopSize(UP, FullUnrollTripCount)` - Stops setting `TripCount` and `MaxTripCount` prior to calling `shouldFullUnroll()` - Removes the `UP.Count = 0` safeguards - Swaps `<` with `<=`, to address the `UP.Force == false` case - Adds a test to document the behavior change (no longer leaking `MaxTripCount`) in the `UP.Force == true` case.
This patch adds dependencies on OpenMP and OpenACC dialects to prevent link errors when compiling with shared libraries.
Fix two bugs in DocNode's comparison operators and add a new Document::copyNode() method: 1. operator== was implemented via operator<, which hits llvm_unreachable for Array/Map nodes. Implement operator== directly with recursive value comparison for all node types. 2. operator< compared KindAndDoc pointers, causing cross-document nodes of the same type and value to silently produce wrong results. Compare by kind then by value instead. 3. Add Document::copyNode() for deep copying nodes between Documents with independent memory ownership.
…missing ; (llvm#188123) Fix an assertion failure in `ParseDecltypeSpecifier` when parsing malformed expressions e.g. `decltype(union { ... )`. When a class/union definition is missing a semicolon, clang's error recovery may synthetically set the current token to `tok::semi` without actually inserting it into the preprocessor's backtrack cache, see https://github.com/llvm/llvm-project/blob/9096c9cda3df4d09c9c6e4efa1a07a232a9ac8f8/clang/lib/Parse/ParseDeclCXX.cpp#L1920-L1927 If `ParseDecltypeSpecifier` later encounters this synthetic semicolon during its own error recovery, its attempts to revert the cache and re-lex the tokens will lead to reading unexpected tokens from the historical stream, failing the strict `Tok.is(tok::semi)` assertion. This patch removes this assertion, acknowledging that during invalid parses and error recovery, the preprocessor's cache state may not strictly align with the parser's simulated state. Fixes: llvm#188014
This is the correct order according to the function prototype. This should be NFC, because for PCH, AllowCompatibleDifferences is always false: it is only used in isAcceptableASTFile, which calls readASTFileControlBlock, which explicitely passes false. We explicitely pass in `nullptr` for Diag, so the incorrect error message isn't printed.
Closes llvm#187699 . Fix incorrect parsing of `ConstArrayAttr`. `parse` method incorrectly used type of `elts` parameter as type of the whole array. This means that when reading back text or bytecode clangir files attribute did not have correct type and correct `trailingZerosNum`. Type was always of inner `elts`, meaning smaller then actual type if any trailing zeros were present and `trailingZerosNum` was always zero.
…lvm#189676) Whether an arith operation can be truncated to a given bitwidth should also depend on the sign semantics of the operation itself. Consider: ``` %input = /* upper bound > INT32_MAX, <= UINT32_MAX */ : index %c0 = arith.constant 0 : index %cmp = arith.cmpi sle, %input, %c0 : index ``` Previously, `checkTruncatability()` would correctly judge that only an unsigned truncation could be legal, however the narrowing would still proceed despite the fact that the `sle` predicate treated the MSB as the sign. Ensure that the sign is checked for signed comparison predicates and for signed elementwise operations by enforcing a `CastKind::Signed` restriction, whereby the narrowing patterns bail out on incompatible input range/operation signedness. **AI tooling usage disclaimer** LIT tests were expanded from manual reproducer examples with LLM assistance. Those additional test cases were verified to regression-test, proofread and edited manually in accordance with the "Human in the loop" policy. LLMs/generative tooling were not used for implementation/documentation purposes. --------- Signed-off-by: Artem Gindinson <gindinson@roofline.ai> Co-authored-by: GPT 5.4 <codex@openai.com>
Like OpenBSD, asan does not support GNU/Hurd yet.
…nteger (llvm#186421) In preparation for updating DIL to handle assignments, this adds a member variable to the DIL Interpreter indicating whether or not updating program variables is allowed. For invocations from the LLDB command prompt (through "frame variable") we want to allow it, but from other places we might not. Therefore we also add new StackFrame ExpressionPathOption, eExpressionPathOptionsAllowVarUpdates, which we add to calls from CommandObjectFrame, and which is checked in GetValueForVariableExpressionPath. Finally, we also add a parameter, can_update_vars, with a default value of true, to ValueObject::SetValueFromInteger, as that will be the main function used to by assignment in DIL.
) In response to [[RFC] Qualifying syntax rule numbers with Fortran standard version in comments](https://discourse.llvm.org/t/rfc-qualifying-syntax-rule-numbers-with-fortran-standard-version-in-comments/90167) this PR adds a section on guidelines for referencing the Fortran Standard.
…lvm#187168) This PR adds code to FoldMemRefAliasOps / --fold-memref-alias-ops to use the new IndexedMemoryAccessOpInterface and IndexedMemCopyOpInterface and implement those operations for relevant operations in the memref dialect. This is a reordering of the changes planned in llvm#177014 and llvm#177016 to make them more testable. There are no behavior changes expected for how memref.load and memref.store behave within the alias ops folding pass, though support for new operations, like memref.prefetch, has been added. Some error messages have been updated because certain laws of memref.load/memref.store have been moved to IndexedAccessOpInterface. Assisted-by: Claude 4.6 (helped deal with some of the boilerplate in the rewrite patterns and with extracting the patch)
…FC (llvm#188808) Replace unsigned with plui or pli_b to better indicate their usage. Templatize the render function and rename it addSExtImm instead of addSImm*Unsigned.
…lvm#189760) Mark this test as UNSUPPORTED for android since android's libc doesn't seem to support aligned_alloc.
This patch implements a new simple region pass that can vectorize store-load chains.
…vm#189696) This patch changes the `Platform::LocateXXX` to return a map from `FileSpec` to `LoadScriptFromSymFile` enum. This is needed for llvm#188722, where I intend to set `LoadScriptFromSymFile` per-module. By default the `Platform::LocateXXX` set the value to whatever the target's current `target.load-script-from-symbol-file` is set to. In llvm#188722 we'll allow overriding this per-target setting on a per-module basis. Drive-by: * Added logging when we fail to load a script.
We have a sshl instruction on RV32 in the 0.21 spec. Unfortunately, we don't have a SSLLI instruction, but we can put a constant shift amount in a register.
This fixes b813b0b. Co-authored-by: Google Bazel Bot <google-bazel-bot@google.com>
Eliminate `MappingRIdx` by making it an identity function. Currently, `MappingRIdx` is used to map the index of an `llvm_any*` type in an intrinsic type signature to its overload index. Eliminating this mapping means that dependent types in LLVM intrinsic definitions (like `LLVMMatchType` and its subclasses) should use the overload index to reference the overload type that it depends on (and not the index within the llvm_any* subset of overloaded types). See https://discourse.llvm.org/t/rfc-simplifying-intrinsics-type-signature-iit-info-generation-encoding-in-intrinsicemitter-cpp/90383
…nsics (llvm#185347) In outer-loop VPlan, avoid emitting vector intrinsic calls for intrinsics without a vector form. In VPRecipeBuilder, detect missing vector intrinsic mapping and emit scalar handling instead of a vector call. Also fix assertion when `llvm.pseudoprobe` in VPlan's native path is being treated as a `WIDEN-INTRINSIC`. Reproducer: https://godbolt.org/z/GsPYobvYs
3472035 to
713e456
Compare
Resolves #189478
Adds code to handle AssertNoFPClass in computeKnownFPClass and adds IR test coverage for X86.