From a5eeb9da054bd76b38e18bedb9015bbaf20605e0 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 6 Sep 2013 12:38:12 +0000 Subject: [PATCH] SelectionDAG: create correct BooleanContent constants Occasionally DAGCombiner can spot that a SETCC operation is completely redundant and reduce it to "all true" or "all false". If this happens to a vector, the value produced has to take account of what a normal comparison would have produced, which may be an all-1s bitmask. The fix in SelectionDAG.cpp is tested, however, as far as I can see the code in TargetLowering.cpp is possibly unreachable and almost certainly irrelevant when triggered so there are no tests. However, I believe it's still clearly the right change and may save someone else some hassle if it suddenly becomes reachable. So I'm doing it anyway. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190147 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 7 +++- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 6 ++- test/CodeGen/X86/vec_setcc.ll | 61 +++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 95dc5ab657d..1472490cca8 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1554,7 +1554,12 @@ SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, case ISD::SETFALSE: case ISD::SETFALSE2: return getConstant(0, VT); case ISD::SETTRUE: - case ISD::SETTRUE2: return getConstant(1, VT); + case ISD::SETTRUE2: { + const TargetLowering *TLI = TM.getTargetLowering(); + TargetLowering::BooleanContent Cnt = TLI->getBooleanContents(VT.isVector()); + return getConstant( + Cnt == TargetLowering::ZeroOrNegativeOneBooleanContent ? -1ULL : 1, VT); + } case ISD::SETOEQ: case ISD::SETOGT: diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index df672214365..f2199d7730d 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1080,7 +1080,11 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, case ISD::SETFALSE: case ISD::SETFALSE2: return DAG.getConstant(0, VT); case ISD::SETTRUE: - case ISD::SETTRUE2: return DAG.getConstant(1, VT); + case ISD::SETTRUE2: { + TargetLowering::BooleanContent Cnt = getBooleanContents(VT.isVector()); + return DAG.getConstant( + Cnt == TargetLowering::ZeroOrNegativeOneBooleanContent ? -1ULL : 1, VT); + } } // Ensure that the constant occurs on the RHS, and fold constant diff --git a/test/CodeGen/X86/vec_setcc.ll b/test/CodeGen/X86/vec_setcc.ll index 6ef23c9bdd0..fc8a56de791 100644 --- a/test/CodeGen/X86/vec_setcc.ll +++ b/test/CodeGen/X86/vec_setcc.ll @@ -124,3 +124,64 @@ define <4 x i32> @v4i32_icmp_ule(<4 x i32> %a, <4 x i32> %b) nounwind readnone s ; AVX: pcmpeqd %xmm1, %xmm0, %xmm0 } +; At one point we were incorrectly constant-folding a setcc to 0x1 instead of +; 0xff, leading to a constpool load. The instruction doesn't matter here, but it +; should set all bits to 1. +define <16 x i8> @test_setcc_constfold_vi8(<16 x i8> %l, <16 x i8> %r) { + %test1 = icmp eq <16 x i8> %l, %r + %mask1 = sext <16 x i1> %test1 to <16 x i8> + + %test2 = icmp ne <16 x i8> %l, %r + %mask2 = sext <16 x i1> %test2 to <16 x i8> + + %res = or <16 x i8> %mask1, %mask2 + ret <16 x i8> %res +; SSE2-LABEL: test_setcc_constfold_vi8: +; SSE2: pcmpeqd %xmm0, %xmm0 + +; SSE41-LABEL: test_setcc_constfold_vi8: +; SSE41: pcmpeqd %xmm0, %xmm0 + +; AVX-LABEL: test_setcc_constfold_vi8: +; AVX: vpcmpeqd %xmm0, %xmm0, %xmm0 +} + +; Make sure sensible results come from doing extension afterwards +define <16 x i8> @test_setcc_constfold_vi1(<16 x i8> %l, <16 x i8> %r) { + %test1 = icmp eq <16 x i8> %l, %r + %test2 = icmp ne <16 x i8> %l, %r + + %res = or <16 x i1> %test1, %test2 + %mask = sext <16 x i1> %res to <16 x i8> + ret <16 x i8> %mask +; SSE2-LABEL: test_setcc_constfold_vi1: +; SSE2: pcmpeqd %xmm0, %xmm0 + +; SSE41-LABEL: test_setcc_constfold_vi1: +; SSE41: pcmpeqd %xmm0, %xmm0 + +; AVX-LABEL: test_setcc_constfold_vi1: +; AVX: vpcmpeqd %xmm0, %xmm0, %xmm0 +} + + +; 64-bit case is also particularly important, as the constant "-1" is probably +; just 32-bits wide. +define <2 x i64> @test_setcc_constfold_vi64(<2 x i64> %l, <2 x i64> %r) { + %test1 = icmp eq <2 x i64> %l, %r + %mask1 = sext <2 x i1> %test1 to <2 x i64> + + %test2 = icmp ne <2 x i64> %l, %r + %mask2 = sext <2 x i1> %test2 to <2 x i64> + + %res = or <2 x i64> %mask1, %mask2 + ret <2 x i64> %res +; SSE2-LABEL: test_setcc_constfold_vi64: +; SSE2: pcmpeqd %xmm0, %xmm0 + +; SSE41-LABEL: test_setcc_constfold_vi64: +; SSE41: pcmpeqd %xmm0, %xmm0 + +; AVX-LABEL: test_setcc_constfold_vi64: +; AVX: vpcmpeqd %xmm0, %xmm0, %xmm0 +} -- 2.11.0