diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2012-10-12 15:42:58 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2012-10-12 15:42:58 +0000 |
commit | 9aa51d1a2c311108192657fcc5bc0861cf9776fa (patch) | |
tree | 1e67b431d656caf3a33cc2cf8975f5da386ced14 | |
parent | e259d912abfd2b8937ad88df280b665a3437804e (diff) | |
download | bcm5719-llvm-9aa51d1a2c311108192657fcc5bc0861cf9776fa.tar.gz bcm5719-llvm-9aa51d1a2c311108192657fcc5bc0861cf9776fa.zip |
Fix big-endian codegen bug in DAGTypeLegalizer::ExpandRes_BITCAST
On PowerPC, a bitcast of <16 x i8> to i128 may run through a code
path in ExpandRes_BITCAST that attempts to do an intermediate
bitcast to a <4 x i32> vector, and then construct the Hi and Lo parts
of the resulting i128 by pairing up two of those i32 vector elements
each. The code already recognizes that on a big-endian system, the
first two vector elements form the Hi part, and the final two vector
elements form the Lo part (vice-versa from the little-endian situation).
However, we also need to take endianness into account when forming each
of those separate pairs: on a big-endian system, vector element 0 is
the *high* part of the pair making up the Hi part of the result, and
vector element 1 is the low part of the pair. The code currently always
uses vector element 0 as the low part and vector element 1 as the high
part, as is appropriate for little-endian platforms only.
This patch fixes this by swapping the vector elements as they are
paired up as appropriate.
llvm-svn: 165802
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 4 | ||||
-rw-r--r-- | llvm/test/CodeGen/PowerPC/2012-10-12-bitcast.ll | 20 |
2 files changed, 24 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index bb54fd24e21..6bcb3b25e98 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -124,6 +124,10 @@ void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) { // there are only two nodes left, i.e. Lo and Hi. SDValue LHS = Vals[Slot]; SDValue RHS = Vals[Slot + 1]; + + if (TLI.isBigEndian()) + std::swap(LHS, RHS); + Vals.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, EVT::getIntegerVT( *DAG.getContext(), diff --git a/llvm/test/CodeGen/PowerPC/2012-10-12-bitcast.ll b/llvm/test/CodeGen/PowerPC/2012-10-12-bitcast.ll new file mode 100644 index 00000000000..e7dc706a889 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/2012-10-12-bitcast.ll @@ -0,0 +1,20 @@ +; RUN: llc < %s | FileCheck %s +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" + +define i32 @test(<16 x i8> %v) nounwind { +entry: + %0 = bitcast <16 x i8> %v to i128 + %1 = lshr i128 %0, 96 + %2 = trunc i128 %1 to i32 + ret i32 %2 +} + +; Verify that bitcast handles big-endian platforms correctly +; by checking we load the result from the correct offset + +; CHECK: addi [[REGISTER:[0-9]+]], 1, -16 +; CHECK: stvx 2, 0, [[REGISTER]] +; CHECK: lwz 3, -16(1) +; CHECK: blr + |