<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Thanks for the test case James, I'll take a look and get back to
you.<br>
<br>
<div class="moz-cite-prefix">On 10/04/2015 12:53, James Molloy
wrote:<br>
</div>
<blockquote
cite="mid:CALCTSA2a2t902w68YZocvQnGsSFjVUyP81Se-NaBbXuEUMp-MA@mail.gmail.com"
type="cite">
<div dir="ltr">Hi Simon,<br>
<br>
<div>This commit was found to be faulty by random testing. The
attached .ll file, when run with "llc crash-2.ll" will fall
over in instruction selection.</div>
<div><br>
</div>
<div>The actual problem is an illegal BUILD_VECTOR is being
created after type legalization (i8/i16 are illegal on
ARM/AArch64).</div>
<div><br>
</div>
<div>Would you mind please having a look?</div>
<div><br>
</div>
<div>Cheers,</div>
<div><br>
</div>
<div>James</div>
<br>
<div class="gmail_quote">On Wed, 25 Mar 2015 at 22:38 Simon
Pilgrim <<a moz-do-not-send="true"
href="mailto:llvm-dev@redking.me.uk">llvm-dev@redking.me.uk</a>>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">Author:
rksimon<br>
Date: Wed Mar 25 17:30:31 2015<br>
New Revision: 233224<br>
<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project?rev=233224&view=rev"
target="_blank">http://llvm.org/viewvc/llvm-project?rev=233224&view=rev</a><br>
Log:<br>
[DAGCombiner] Add support for TRUNCATE + FP_EXTEND vector
constant folding<br>
<br>
This patch adds supports for the vector constant folding of
TRUNCATE and FP_EXTEND instructions and tidies up the
SINT_TO_FP and UINT_TO_FP instructions to match.<br>
<br>
It also moves the vector constant folding for the FNEG and
FABS instructions to use the DAG.getNode() functionality
like the other unary instructions.<br>
<br>
Differential Revision: <a moz-do-not-send="true"
href="http://reviews.llvm.org/D8593" target="_blank">http://reviews.llvm.org/D8593</a><br>
<br>
Modified:<br>
llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h<br>
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
llvm/trunk/test/CodeGen/X86/vec_fpext.ll<br>
llvm/trunk/test/CodeGen/X86/vector-trunc.ll<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=233224&r1=233223&r2=233224&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=233224&r1=233223&r2=233224&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
(original)<br>
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Wed
Mar 25 17:30:31 2015<br>
@@ -94,6 +94,10 @@ namespace ISD {<br>
/// all ConstantSDNode or undef.<br>
bool isBuildVectorOfConstantSDNodes(const SDNode *N);<br>
<br>
+ /// \brief Return true if the specified node is a
BUILD_VECTOR node of<br>
+ /// all ConstantFPSDNode or undef.<br>
+ bool isBuildVectorOfConstantFPSDNodes(const SDNode *N);<br>
+<br>
/// Return true if the specified node is a<br>
/// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node
where only the low<br>
/// element is not an undef.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=233224&r1=233223&r2=233224&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=233224&r1=233223&r2=233224&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
(original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed
Mar 25 17:30:31 2015<br>
@@ -251,7 +251,6 @@ namespace {<br>
SDValue visitORLike(SDValue N0, SDValue N1, SDNode
*LocReference);<br>
SDValue visitXOR(SDNode *N);<br>
SDValue SimplifyVBinOp(SDNode *N);<br>
- SDValue SimplifyVUnaryOp(SDNode *N);<br>
SDValue visitSHL(SDNode *N);<br>
SDValue visitSRA(SDNode *N);<br>
SDValue visitSRL(SDNode *N);<br>
@@ -716,6 +715,22 @@ static SDNode
*isConstantBuildVectorOrCo<br>
return nullptr;<br>
}<br>
<br>
+static SDNode *isConstantIntBuildVectorOrConstantInt(SDValue
N) {<br>
+ if (isa<ConstantSDNode>(N))<br>
+ return N.getNode();<br>
+ if (ISD::isBuildVectorOfConstantSDNodes(N.getNode()))<br>
+ return N.getNode();<br>
+ return nullptr;<br>
+}<br>
+<br>
+static SDNode *isConstantFPBuildVectorOrConstantFP(SDValue
N) {<br>
+ if (isa<ConstantFPSDNode>(N))<br>
+ return N.getNode();<br>
+ if (ISD::isBuildVectorOfConstantFPSDNodes(N.getNode()))<br>
+ return N.getNode();<br>
+ return nullptr;<br>
+}<br>
+<br>
// \brief Returns the SDNode if it is a constant splat
BuildVector or constant<br>
// int.<br>
static ConstantSDNode *isConstOrConstSplat(SDValue N) {<br>
@@ -6557,7 +6572,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNod<br>
if (N0.getValueType() == N->getValueType(0))<br>
return N0;<br>
// fold (truncate c1) -> c1<br>
- if (isa<ConstantSDNode>(N0))<br>
+ if (isConstantIntBuildVectorOrConstantInt(N0))<br>
return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, N0);<br>
// fold (truncate (truncate x)) -> (truncate x)<br>
if (N0.getOpcode() == ISD::TRUNCATE)<br>
@@ -7947,8 +7962,7 @@ SDValue DAGCombiner::visitSINT_TO_FP(SDN<br>
EVT OpVT = N0.getValueType();<br>
<br>
// fold (sint_to_fp c1) -> c1fp<br>
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);<br>
- if (N0C &&<br>
+ if (isConstantIntBuildVectorOrConstantInt(N0) &&<br>
// ...but only if the target supports immediate
floating-point values<br>
(!LegalOperations ||<br>
TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP,
VT)))<br>
@@ -8000,8 +8014,7 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDN<br>
EVT OpVT = N0.getValueType();<br>
<br>
// fold (uint_to_fp c1) -> c1fp<br>
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);<br>
- if (N0C &&<br>
+ if (isConstantIntBuildVectorOrConstantInt(N0) &&<br>
// ...but only if the target supports immediate
floating-point values<br>
(!LegalOperations ||<br>
TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP,
VT)))<br>
@@ -8159,7 +8172,6 @@ SDValue DAGCombiner::visitFP_ROUND_INREG<br>
<br>
SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) {<br>
SDValue N0 = N->getOperand(0);<br>
- ConstantFPSDNode *N0CFP =
dyn_cast<ConstantFPSDNode>(N0);<br>
EVT VT = N->getValueType(0);<br>
<br>
// If this is fp_round(fpextend), don't fold it, allow
ourselves to be folded.<br>
@@ -8168,7 +8180,7 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNo<br>
return SDValue();<br>
<br>
// fold (fp_extend c1fp) -> c1fp<br>
- if (N0CFP)<br>
+ if (isConstantFPBuildVectorOrConstantFP(N0))<br>
return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, N0);<br>
<br>
// Turn fp_extend(fp_round(X, 1)) -> x since the
fp_round doesn't affect the<br>
@@ -8243,14 +8255,9 @@ SDValue DAGCombiner::visitFNEG(SDNode
*N<br>
SDValue N0 = N->getOperand(0);<br>
EVT VT = N->getValueType(0);<br>
<br>
- if (VT.isVector()) {<br>
- SDValue FoldedVOp = SimplifyVUnaryOp(N);<br>
- if (FoldedVOp.getNode()) return FoldedVOp;<br>
- }<br>
-<br>
// Constant fold FNEG.<br>
- if (isa<ConstantFPSDNode>(N0))<br>
- return DAG.getNode(ISD::FNEG, SDLoc(N), VT,
N->getOperand(0));<br>
+ if (isConstantFPBuildVectorOrConstantFP(N0))<br>
+ return DAG.getNode(ISD::FNEG, SDLoc(N), VT, N0);<br>
<br>
if (isNegatibleForFree(N0, LegalOperations,
DAG.getTargetLoweringInfo(),<br>
&DAG.getTarget().Options))<br>
@@ -8345,13 +8352,8 @@ SDValue DAGCombiner::visitFABS(SDNode
*N<br>
SDValue N0 = N->getOperand(0);<br>
EVT VT = N->getValueType(0);<br>
<br>
- if (VT.isVector()) {<br>
- SDValue FoldedVOp = SimplifyVUnaryOp(N);<br>
- if (FoldedVOp.getNode()) return FoldedVOp;<br>
- }<br>
-<br>
// fold (fabs c1) -> fabs(c1)<br>
- if (isa<ConstantFPSDNode>(N0))<br>
+ if (isConstantFPBuildVectorOrConstantFP(N0))<br>
return DAG.getNode(ISD::FABS, SDLoc(N), VT, N0);<br>
<br>
// fold (fabs (fabs x)) -> (fabs x)<br>
@@ -12401,38 +12403,6 @@ SDValue
DAGCombiner::SimplifyVBinOp(SDNo<br>
return SDValue();<br>
}<br>
<br>
-/// Visit a binary vector operation, like FABS/FNEG.<br>
-SDValue DAGCombiner::SimplifyVUnaryOp(SDNode *N) {<br>
- assert(N->getValueType(0).isVector() &&<br>
- "SimplifyVUnaryOp only works on vectors!");<br>
-<br>
- SDValue N0 = N->getOperand(0);<br>
-<br>
- if (N0.getOpcode() != ISD::BUILD_VECTOR)<br>
- return SDValue();<br>
-<br>
- // Operand is a BUILD_VECTOR node, see if we can constant
fold it.<br>
- SmallVector<SDValue, 8> Ops;<br>
- for (unsigned i = 0, e = N0.getNumOperands(); i != e;
++i) {<br>
- SDValue Op = N0.getOperand(i);<br>
- if (Op.getOpcode() != ISD::UNDEF &&<br>
- Op.getOpcode() != ISD::ConstantFP)<br>
- break;<br>
- EVT EltVT = Op.getValueType();<br>
- SDValue FoldOp = DAG.getNode(N->getOpcode(),
SDLoc(N0), EltVT, Op);<br>
- if (FoldOp.getOpcode() != ISD::UNDEF &&<br>
- FoldOp.getOpcode() != ISD::ConstantFP)<br>
- break;<br>
- Ops.push_back(FoldOp);<br>
- AddToWorklist(FoldOp.getNode());<br>
- }<br>
-<br>
- if (Ops.size() != N0.getNumOperands())<br>
- return SDValue();<br>
-<br>
- return DAG.getNode(ISD::BUILD_VECTOR, SDLoc(N),
N0.getValueType(), Ops);<br>
-}<br>
-<br>
SDValue DAGCombiner::SimplifySelect(SDLoc DL, SDValue N0,<br>
SDValue N1, SDValue
N2){<br>
assert(N0.getOpcode() ==ISD::SETCC && "First
argument must be a SetCC node!");<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=233224&r1=233223&r2=233224&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=233224&r1=233223&r2=233224&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
(original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed
Mar 25 17:30:31 2015<br>
@@ -196,6 +196,22 @@ bool ISD::isBuildVectorOfConstantSDNodes<br>
return true;<br>
}<br>
<br>
+/// \brief Return true if the specified node is a
BUILD_VECTOR node of<br>
+/// all ConstantFPSDNode or undef.<br>
+bool ISD::isBuildVectorOfConstantFPSDNodes(const SDNode *N)
{<br>
+ if (N->getOpcode() != ISD::BUILD_VECTOR)<br>
+ return false;<br>
+<br>
+ for (unsigned i = 0, e = N->getNumOperands(); i != e;
++i) {<br>
+ SDValue Op = N->getOperand(i);<br>
+ if (Op.getOpcode() == ISD::UNDEF)<br>
+ continue;<br>
+ if (!isa<ConstantFPSDNode>(Op))<br>
+ return false;<br>
+ }<br>
+ return true;<br>
+}<br>
+<br>
/// isScalarToVector - Return true if the specified node is
a<br>
/// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where
only the low<br>
/// element is not an undef.<br>
@@ -2827,7 +2843,7 @@ SDValue SelectionDAG::getNode(unsigned
O<br>
}<br>
}<br>
<br>
- // Constant fold unary operations with a vector integer
operand.<br>
+ // Constant fold unary operations with a vector integer
or float operand.<br>
if (BuildVectorSDNode *BV =
dyn_cast<BuildVectorSDNode>(Operand.getNode())) {<br>
if (BV->isConstant()) {<br>
switch (Opcode) {<br>
@@ -2835,6 +2851,10 @@ SDValue
SelectionDAG::getNode(unsigned O<br>
// FIXME: Entirely reasonable to perform folding of
other unary<br>
// operations here as the need arises.<br>
break;<br>
+ case ISD::FNEG:<br>
+ case ISD::FABS:<br>
+ case ISD::FP_EXTEND:<br>
+ case ISD::TRUNCATE:<br>
case ISD::UINT_TO_FP:<br>
case ISD::SINT_TO_FP: {<br>
// Let the above scalar folding handle the folding
of each element.<br>
@@ -2842,9 +2862,14 @@ SDValue
SelectionDAG::getNode(unsigned O<br>
for (int i = 0, e = VT.getVectorNumElements(); i !=
e; ++i) {<br>
SDValue OpN = BV->getOperand(i);<br>
OpN = getNode(Opcode, DL,
VT.getVectorElementType(), OpN);<br>
+ if (OpN.getOpcode() != ISD::UNDEF &&<br>
+ OpN.getOpcode() != ISD::Constant &&<br>
+ OpN.getOpcode() != ISD::ConstantFP)<br>
+ break;<br>
Ops.push_back(OpN);<br>
}<br>
- return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);<br>
+ if (Ops.size() == VT.getVectorNumElements())<br>
+ return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);<br>
}<br>
}<br>
}<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/vec_fpext.ll<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_fpext.ll?rev=233224&r1=233223&r2=233224&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_fpext.ll?rev=233224&r1=233223&r2=233224&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/vec_fpext.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/vec_fpext.ll Wed Mar 25
17:30:31 2015<br>
@@ -42,3 +42,15 @@ entry:<br>
store <8 x double> %1, <8 x double>* %out,
align 1<br>
ret void<br>
}<br>
+<br>
+define <2 x double> @fpext_fromconst() {<br>
+; CHECK-LABEL: fpext_fromconst:<br>
+; AVX-LABEL: fpext_fromconst:<br>
+entry:<br>
+; CHECK: movaps {{.*#+}} xmm0 =
[1.000000e+00,-2.000000e+00]<br>
+; AVX: vmovaps {{.*#+}} xmm0 = [1.000000e+00,-2.000000e+00]<br>
+ %0 = insertelement <2 x float> undef, float 1.0,
i32 0<br>
+ %1 = insertelement <2 x float> %0, float -2.0, i32
1<br>
+ %2 = fpext <2 x float> %1 to <2 x double><br>
+ ret <2 x double> %2<br>
+}<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/vector-trunc.ll<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vector-trunc.ll?rev=233224&r1=233223&r2=233224&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vector-trunc.ll?rev=233224&r1=233223&r2=233224&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/vector-trunc.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/vector-trunc.ll Wed Mar 25
17:30:31 2015<br>
@@ -221,3 +221,20 @@ entry:<br>
%1 = bitcast <8 x i8> %0 to i64<br>
ret i64 %1<br>
}<br>
+<br>
+define <16 x i8> @trunc16i64_const() {<br>
+; SSE-LABEL: trunc16i64_const<br>
+; SSE: # BB#0: # %entry<br>
+; SSE-NEXT: xorps %xmm0, %xmm0<br>
+; SSE-NEXT: retq<br>
+;<br>
+; AVX-LABEL: trunc16i64_const<br>
+; AVX: # BB#0: # %entry<br>
+; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0<br>
+; AVX-NEXT: retq<br>
+<br>
+entry:<br>
+ %0 = trunc <16 x i64> zeroinitializer to <16 x
i8><br>
+ %1 = shufflevector <16 x i8> %0, <16 x i8>
%0, <16 x i32> <i32 28, i32 30, i32 0, i32 2, i32
4, i32 6, i32 8, i32 10, i32 undef, i32 14, i32 16, i32 18,
i32 20, i32 22, i32 24, i32 26><br>
+ ret <16 x i8> %1<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a moz-do-not-send="true"
href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a moz-do-not-send="true"
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits"
target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote>
</div>
</div>
</blockquote>
<br>
</body>
</html>