[SDAG] When performing post-legalize DAG combining, run the legalizer

over each node in the worklist prior to combining.

This allows the combiner to produce new nodes which need to go back
through legalization. This is particularly useful when generating
operands to target specific nodes in a post-legalize DAG combine where
the operands are significantly easier to express as pre-legalized
operations. My immediate use case will be PSHUFB formation where we need
to build a constant shuffle mask with a build_vector node.

This also refactors the relevant functionality in the legalizer to
support this, and updates relevant tests. I've spoken to the R600 folks
and these changes look like improvements to them. The avx512 change
needs to be investigated, I suspect there is a disagreement between the
legalizer and the DAG combiner there, but it seems a minor issue so
leaving it to be re-evaluated after this patch.

Differential Revision: http://reviews.llvm.org/D4564

llvm-svn: 214020
This commit is contained in:
Chandler Carruth 2014-07-26 05:49:40 +00:00
parent d7c726c5e9
commit 411fb407f8
7 changed files with 159 additions and 93 deletions

View File

@ -16,6 +16,7 @@
#define LLVM_CODEGEN_SELECTIONDAG_H #define LLVM_CODEGEN_SELECTIONDAG_H
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/DAGCombine.h"
@ -364,6 +365,27 @@ public:
/// the graph. /// the graph.
void Legalize(); void Legalize();
/// \brief Transforms a SelectionDAG node and any operands to it into a node
/// that is compatible with the target instruction selector, as indicated by
/// the TargetLowering object.
///
/// \returns true if \c N is a valid, legal node after calling this.
///
/// This essentially runs a single recursive walk of the \c Legalize process
/// over the given node (and its operands). This can be used to incrementally
/// legalize the DAG. All of the nodes which are directly replaced,
/// potentially including N, are added to the output parameter \c
/// UpdatedNodes so that the delta to the DAG can be understood by the
/// caller.
///
/// When this returns false, N has been legalized in a way that make the
/// pointer passed in no longer valid. It may have even been deleted from the
/// DAG, and so it shouldn't be used further. When this returns true, the
/// N passed in is a legal node, and can be immediately processed as such.
/// This may still have done some work on the DAG, and will still populate
/// UpdatedNodes with any new nodes replacing those originally in the DAG.
bool LegalizeOp(SDNode *N, SmallSetVector<SDNode *, 16> &UpdatedNodes);
/// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG
/// that only uses vector math operations supported by the target. This is /// that only uses vector math operations supported by the target. This is
/// necessary as a separate step from Legalize because unrolling a vector /// necessary as a separate step from Legalize because unrolling a vector

View File

@ -1136,10 +1136,6 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
// changes of the root. // changes of the root.
HandleSDNode Dummy(DAG.getRoot()); HandleSDNode Dummy(DAG.getRoot());
// The root of the dag may dangle to deleted nodes until the dag combiner is
// done. Set it to null to avoid confusion.
DAG.setRoot(SDValue());
// while the worklist isn't empty, find a node and // while the worklist isn't empty, find a node and
// try and combine it. // try and combine it.
while (!WorklistMap.empty()) { while (!WorklistMap.empty()) {
@ -1173,6 +1169,20 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
WorklistRemover DeadNodes(*this); WorklistRemover DeadNodes(*this);
// If this combine is running after legalizing the DAG, re-legalize any
// nodes pulled off the worklist.
if (Level == AfterLegalizeDAG) {
SmallSetVector<SDNode *, 16> UpdatedNodes;
bool NIsValid = DAG.LegalizeOp(N, UpdatedNodes);
for (SDNode *LN : UpdatedNodes) {
AddToWorklist(LN);
AddUsersToWorklist(LN);
}
if (!NIsValid)
continue;
}
SDValue RV = combine(N); SDValue RV = combine(N);
if (!RV.getNode()) if (!RV.getNode())

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -53,11 +54,16 @@ class SelectionDAGLegalize : public SelectionDAG::DAGUpdateListener {
const TargetLowering &TLI; const TargetLowering &TLI;
SelectionDAG &DAG; SelectionDAG &DAG;
/// LegalizePosition - The iterator for walking through the node list. /// \brief The iterator being used to walk the DAG. We hold a reference to it
SelectionDAG::allnodes_iterator LegalizePosition; /// in order to update it as necessary on node deletion.
SelectionDAG::allnodes_iterator &LegalizePosition;
/// LegalizedNodes - The set of nodes which have already been legalized. /// \brief The set of nodes which have already been legalized. We hold a
SmallPtrSet<SDNode *, 16> LegalizedNodes; /// reference to it in order to update as necessary on node deletion.
SmallPtrSetImpl<SDNode *> &LegalizedNodes;
/// \brief A set of all the nodes updated during legalization.
SmallSetVector<SDNode *, 16> *UpdatedNodes;
EVT getSetCCResultType(EVT VT) const { EVT getSetCCResultType(EVT VT) const {
return TLI.getSetCCResultType(*DAG.getContext(), VT); return TLI.getSetCCResultType(*DAG.getContext(), VT);
@ -66,14 +72,19 @@ class SelectionDAGLegalize : public SelectionDAG::DAGUpdateListener {
// Libcall insertion helpers. // Libcall insertion helpers.
public: public:
explicit SelectionDAGLegalize(SelectionDAG &DAG); SelectionDAGLegalize(SelectionDAG &DAG,
SelectionDAG::allnodes_iterator &LegalizePosition,
SmallPtrSetImpl<SDNode *> &LegalizedNodes,
SmallSetVector<SDNode *, 16> *UpdatedNodes = nullptr)
: SelectionDAG::DAGUpdateListener(DAG), TM(DAG.getTarget()),
TLI(DAG.getTargetLoweringInfo()), DAG(DAG),
LegalizePosition(LegalizePosition), LegalizedNodes(LegalizedNodes),
UpdatedNodes(UpdatedNodes) {}
void LegalizeDAG(); /// \brief Legalizes the given operation.
private:
/// LegalizeOp - Legalizes the given operation.
void LegalizeOp(SDNode *Node); void LegalizeOp(SDNode *Node);
private:
SDValue OptimizeFloatStore(StoreSDNode *ST); SDValue OptimizeFloatStore(StoreSDNode *ST);
void LegalizeLoadOps(SDNode *Node); void LegalizeLoadOps(SDNode *Node);
@ -149,6 +160,8 @@ private:
LegalizedNodes.erase(N); LegalizedNodes.erase(N);
if (LegalizePosition == SelectionDAG::allnodes_iterator(N)) if (LegalizePosition == SelectionDAG::allnodes_iterator(N))
++LegalizePosition; ++LegalizePosition;
if (UpdatedNodes)
UpdatedNodes->remove(N);
} }
public: public:
@ -168,14 +181,25 @@ public:
} }
void ReplaceNode(SDNode *Old, SDNode *New) { void ReplaceNode(SDNode *Old, SDNode *New) {
DAG.ReplaceAllUsesWith(Old, New); DAG.ReplaceAllUsesWith(Old, New);
for (unsigned i = 0, e = Old->getNumValues(); i != e; ++i)
DAG.TransferDbgValues(SDValue(Old, i), SDValue(New, i));
if (UpdatedNodes)
UpdatedNodes->insert(New);
ReplacedNode(Old); ReplacedNode(Old);
} }
void ReplaceNode(SDValue Old, SDValue New) { void ReplaceNode(SDValue Old, SDValue New) {
DAG.ReplaceAllUsesWith(Old, New); DAG.ReplaceAllUsesWith(Old, New);
DAG.TransferDbgValues(Old, New);
if (UpdatedNodes)
UpdatedNodes->insert(New.getNode());
ReplacedNode(Old.getNode()); ReplacedNode(Old.getNode());
} }
void ReplaceNode(SDNode *Old, const SDValue *New) { void ReplaceNode(SDNode *Old, const SDValue *New) {
DAG.ReplaceAllUsesWith(Old, New); DAG.ReplaceAllUsesWith(Old, New);
for (unsigned i = 0, e = Old->getNumValues(); i != e; ++i)
DAG.TransferDbgValues(SDValue(Old, i), New[i]);
if (UpdatedNodes)
UpdatedNodes->insert(New->getNode());
ReplacedNode(Old); ReplacedNode(Old);
} }
}; };
@ -213,40 +237,6 @@ SelectionDAGLegalize::ShuffleWithNarrowerEltType(EVT NVT, EVT VT, SDLoc dl,
return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]);
} }
SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag)
: SelectionDAG::DAGUpdateListener(dag),
TM(dag.getTarget()), TLI(dag.getTargetLoweringInfo()),
DAG(dag) {
}
void SelectionDAGLegalize::LegalizeDAG() {
DAG.AssignTopologicalOrder();
// Visit all the nodes. We start in topological order, so that we see
// nodes with their original operands intact. Legalization can produce
// new nodes which may themselves need to be legalized. Iterate until all
// nodes have been legalized.
for (;;) {
bool AnyLegalized = false;
for (LegalizePosition = DAG.allnodes_end();
LegalizePosition != DAG.allnodes_begin(); ) {
--LegalizePosition;
SDNode *N = LegalizePosition;
if (LegalizedNodes.insert(N)) {
AnyLegalized = true;
LegalizeOp(N);
}
}
if (!AnyLegalized)
break;
}
// Remove dead nodes now.
DAG.RemoveDeadNodes();
}
/// ExpandConstantFP - Expands the ConstantFP node to an integer constant or /// ExpandConstantFP - Expands the ConstantFP node to an integer constant or
/// a load from the constant pool. /// a load from the constant pool.
SDValue SDValue
@ -928,6 +918,10 @@ void SelectionDAGLegalize::LegalizeLoadOps(SDNode *Node) {
assert(RVal.getNode() != Node && "Load must be completely replaced"); assert(RVal.getNode() != Node && "Load must be completely replaced");
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), RVal); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), RVal);
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), RChain); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), RChain);
if (UpdatedNodes) {
UpdatedNodes->insert(RVal.getNode());
UpdatedNodes->insert(RChain.getNode());
}
ReplacedNode(Node); ReplacedNode(Node);
} }
return; return;
@ -1148,6 +1142,10 @@ void SelectionDAGLegalize::LegalizeLoadOps(SDNode *Node) {
assert(Value.getNode() != Node && "Load must be completely replaced"); assert(Value.getNode() != Node && "Load must be completely replaced");
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), Value); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), Value);
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), Chain); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), Chain);
if (UpdatedNodes) {
UpdatedNodes->insert(Value.getNode());
UpdatedNodes->insert(Chain.getNode());
}
ReplacedNode(Node); ReplacedNode(Node);
} }
} }
@ -1335,10 +1333,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
} }
if (NewNode != Node) { if (NewNode != Node) {
DAG.ReplaceAllUsesWith(Node, NewNode); ReplaceNode(Node, NewNode);
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
DAG.TransferDbgValues(SDValue(Node, i), SDValue(NewNode, i));
ReplacedNode(Node);
Node = NewNode; Node = NewNode;
} }
switch (Action) { switch (Action) {
@ -1356,12 +1351,8 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
else else
ResultVals.push_back(Res.getValue(i)); ResultVals.push_back(Res.getValue(i));
} }
if (Res.getNode() != Node || Res.getResNo() != 0) { if (Res.getNode() != Node || Res.getResNo() != 0)
DAG.ReplaceAllUsesWith(Node, ResultVals.data()); ReplaceNode(Node, ResultVals.data());
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
DAG.TransferDbgValues(SDValue(Node, i), ResultVals[i]);
ReplacedNode(Node);
}
return; return;
} }
} }
@ -4179,6 +4170,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
// use the new one. // use the new one.
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), Tmp2); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), Tmp2);
DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), Chain); DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), Chain);
if (UpdatedNodes) {
UpdatedNodes->insert(Tmp2.getNode());
UpdatedNodes->insert(Chain.getNode());
}
ReplacedNode(Node); ReplacedNode(Node);
break; break;
} }
@ -4285,7 +4280,48 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
// SelectionDAG::Legalize - This is the entry point for the file. // SelectionDAG::Legalize - This is the entry point for the file.
// //
void SelectionDAG::Legalize() { void SelectionDAG::Legalize() {
/// run - This is the main entry point to this class. AssignTopologicalOrder();
///
SelectionDAGLegalize(*this).LegalizeDAG(); allnodes_iterator LegalizePosition;
SmallPtrSet<SDNode *, 16> LegalizedNodes;
SelectionDAGLegalize Legalizer(*this, LegalizePosition, LegalizedNodes);
// Visit all the nodes. We start in topological order, so that we see
// nodes with their original operands intact. Legalization can produce
// new nodes which may themselves need to be legalized. Iterate until all
// nodes have been legalized.
for (;;) {
bool AnyLegalized = false;
for (LegalizePosition = allnodes_end();
LegalizePosition != allnodes_begin(); ) {
--LegalizePosition;
SDNode *N = LegalizePosition;
if (LegalizedNodes.insert(N)) {
AnyLegalized = true;
Legalizer.LegalizeOp(N);
}
}
if (!AnyLegalized)
break;
}
// Remove dead nodes now.
RemoveDeadNodes();
}
bool SelectionDAG::LegalizeOp(SDNode *N,
SmallSetVector<SDNode *, 16> &UpdatedNodes) {
allnodes_iterator LegalizePosition(N);
SmallPtrSet<SDNode *, 16> LegalizedNodes;
SelectionDAGLegalize Legalizer(*this, LegalizePosition, LegalizedNodes,
&UpdatedNodes);
// Directly insert the node in question, and legalize it. This will recurse
// as needed through operands.
LegalizedNodes.insert(N);
Legalizer.LegalizeOp(N);
return LegalizedNodes.count(N);
} }

View File

@ -49,8 +49,8 @@ define void @fp_to_sint_v4i32(<4 x i32> addrspace(1)* %out, <4 x float> addrspac
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG: SUB_INT ; EG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; Check that the compiler doesn't crash with a "cannot select" error ; Check that the compiler doesn't crash with a "cannot select" error
; SI: S_ENDPGM ; SI: S_ENDPGM
@ -81,8 +81,8 @@ entry:
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -102,8 +102,8 @@ entry:
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; SI: S_ENDPGM ; SI: S_ENDPGM
define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) { define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
@ -132,8 +132,8 @@ define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -153,8 +153,8 @@ define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -174,8 +174,8 @@ define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -195,8 +195,8 @@ define void @fp_to_sint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; SI: S_ENDPGM ; SI: S_ENDPGM
define void @fp_to_sint_v4i64(<4 x i64> addrspace(1)* %out, <4 x float> %x) { define void @fp_to_sint_v4i64(<4 x i64> addrspace(1)* %out, <4 x float> %x) {

View File

@ -52,8 +52,8 @@ define void @fp_to_uint_v4i32(<4 x i32> addrspace(1)* %out, <4 x float> addrspac
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG: SUB_INT ; EG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; SI: S_ENDPGM ; SI: S_ENDPGM
define void @fp_to_uint_i64(i64 addrspace(1)* %out, float %x) { define void @fp_to_uint_i64(i64 addrspace(1)* %out, float %x) {
@ -82,8 +82,8 @@ define void @fp_to_uint_i64(i64 addrspace(1)* %out, float %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -103,8 +103,8 @@ define void @fp_to_uint_i64(i64 addrspace(1)* %out, float %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; SI: S_ENDPGM ; SI: S_ENDPGM
define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) { define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
@ -133,8 +133,8 @@ define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -154,8 +154,8 @@ define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -175,8 +175,8 @@ define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: AND_INT ; EG-DAG: AND_INT
; EG-DAG: LSHR ; EG-DAG: LSHR
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
@ -196,8 +196,8 @@ define void @fp_to_uint_v2i64(<2 x i64> addrspace(1)* %out, <2 x float> %x) {
; EG-DAG: XOR_INT ; EG-DAG: XOR_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: SUB_INT ; EG-DAG: SUB_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; EG-DAG: CNDGE_INT ; EG-DAG: CNDE_INT
; SI: S_ENDPGM ; SI: S_ENDPGM
define void @fp_to_uint_v4i64(<4 x i64> addrspace(1)* %out, <4 x float> %x) { define void @fp_to_uint_v4i64(<4 x i64> addrspace(1)* %out, <4 x float> %x) {

View File

@ -1,5 +1,4 @@
; RUN: llc -march=r600 -mcpu=cypress < %s | FileCheck -check-prefix=EG %s ; RUN: llc -march=r600 -mcpu=cypress < %s | FileCheck -check-prefix=EG %s
; XFAIL: *
; EG-LABEL: @and_setcc_setcc_i32 ; EG-LABEL: @and_setcc_setcc_i32
; EG: AND_INT ; EG: AND_INT

View File

@ -28,10 +28,9 @@ l2:
ret float %c1 ret float %c1
} }
; FIXME: Can use vcmpeqss and extract from the mask here in AVX512.
; CHECK-LABEL: test3 ; CHECK-LABEL: test3
; CHECK: vcmpeqss ; CHECK: vucomiss {{.*}}encoding: [0x62
; CHECK: kmov
; CHECK: ret
define i32 @test3(float %a, float %b) { define i32 @test3(float %a, float %b) {
%cmp10.i = fcmp oeq float %a, %b %cmp10.i = fcmp oeq float %a, %b