mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[PATCH] Correct type used for VADD_SPLAT optimization on PowerPC
In PPCISelLowering.cpp: PPCTargetLowering::LowerBUILD_VECTOR(), there is an optimization for certain patterns to generate one or two vector splats followed by a vector add or subtract. This operation is represented by a VADD_SPLAT in the selection DAG. Prior to this patch, it was possible for the VADD_SPLAT to be assigned the wrong data type, causing incorrect code generation. This patch corrects the problem. Specifically, the code previously assigned the value type of the BUILD_VECTOR node to the newly generated VADD_SPLAT node. This is correct much of the time, but not always. The problem is that the call to isConstantSplat() may return a SplatBitSize that is not the same as the number of bits in the original element vector type. The correct type to assign is a vector type with the same element bit size as SplatBitSize. The included test case shows an example of this, where the BUILD_VECTOR node has a type of v16i8. The vector to be built is {0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16}. isConstantSplat detects that we can generate a splat of 16 for type v8i16, which is the type we must assign to the VADD_SPLAT node. If we do not, we generate a vspltisb of 8 and a vaddubm, which generates the incorrect result {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}. The correct code generation is a vspltish of 8 and a vadduhm. This patch also corrected code generation for CodeGen/PowerPC/2008-07-10-SplatMiscompile.ll, which had been marked as an XFAIL, so we can remove the XFAIL from the test case. llvm-svn: 209662
This commit is contained in:
parent
62d7aed204
commit
b806d02b5b
@ -5531,10 +5531,14 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op,
|
||||
// we convert to a pseudo that will be expanded later into one of
|
||||
// the above forms.
|
||||
SDValue Elt = DAG.getConstant(SextVal, MVT::i32);
|
||||
EVT VT = Op.getValueType();
|
||||
int Size = VT == MVT::v16i8 ? 1 : (VT == MVT::v8i16 ? 2 : 4);
|
||||
SDValue EltSize = DAG.getConstant(Size, MVT::i32);
|
||||
return DAG.getNode(PPCISD::VADD_SPLAT, dl, VT, Elt, EltSize);
|
||||
EVT VT = (SplatSize == 1 ? MVT::v16i8 :
|
||||
(SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
|
||||
SDValue EltSize = DAG.getConstant(SplatSize, MVT::i32);
|
||||
SDValue RetVal = DAG.getNode(PPCISD::VADD_SPLAT, dl, VT, Elt, EltSize);
|
||||
if (VT == Op.getValueType())
|
||||
return RetVal;
|
||||
else
|
||||
return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), RetVal);
|
||||
}
|
||||
|
||||
// If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is
|
||||
|
@ -1,6 +1,5 @@
|
||||
; RUN: llc < %s -march=ppc32 -mcpu=g5 | grep vadduhm
|
||||
; RUN: llc < %s -march=ppc32 -mcpu=g5 | grep vsubuhm
|
||||
; XFAIL: *
|
||||
|
||||
define <4 x i32> @test() nounwind {
|
||||
ret <4 x i32> < i32 4293066722, i32 4293066722, i32 4293066722, i32 4293066722>
|
||||
|
18
test/CodeGen/PowerPC/splat-bug.ll
Normal file
18
test/CodeGen/PowerPC/splat-bug.ll
Normal file
@ -0,0 +1,18 @@
|
||||
; RUN: llc -mcpu=ppc64 -O0 -fast-isel=false < %s | FileCheck %s
|
||||
|
||||
; Checks for a previous bug where vspltisb/vaddubm were issued in place
|
||||
; of vsplitsh/vadduhm.
|
||||
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
@a = external global <16 x i8>
|
||||
|
||||
define void @foo() nounwind ssp {
|
||||
; CHECK: foo:
|
||||
store <16 x i8> <i8 0, i8 16, i8 0, i8 16, i8 0, i8 16, i8 0, i8 16, i8 0, i8 16, i8 0, i8 16, i8 0, i8 16, i8 0, i8 16>, <16 x i8>* @a
|
||||
; CHECK: vspltish [[REG:[0-9]+]], 8
|
||||
; CHECK: vadduhm {{[0-9]+}}, [[REG]], [[REG]]
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user