1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

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.

llvm-svn: 190147
This commit is contained in:
Tim Northover 2013-09-06 12:38:12 +00:00
parent d9577fe859
commit 5e921518f7
3 changed files with 72 additions and 2 deletions

View File

@ -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:

View File

@ -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

View File

@ -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
}