mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-02 00:35:27 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165802 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4c856ee1f8
commit
7bbb9c7b4a
@ -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.
|
// there are only two nodes left, i.e. Lo and Hi.
|
||||||
SDValue LHS = Vals[Slot];
|
SDValue LHS = Vals[Slot];
|
||||||
SDValue RHS = Vals[Slot + 1];
|
SDValue RHS = Vals[Slot + 1];
|
||||||
|
|
||||||
|
if (TLI.isBigEndian())
|
||||||
|
std::swap(LHS, RHS);
|
||||||
|
|
||||||
Vals.push_back(DAG.getNode(ISD::BUILD_PAIR, dl,
|
Vals.push_back(DAG.getNode(ISD::BUILD_PAIR, dl,
|
||||||
EVT::getIntegerVT(
|
EVT::getIntegerVT(
|
||||||
*DAG.getContext(),
|
*DAG.getContext(),
|
||||||
|
20
test/CodeGen/PowerPC/2012-10-12-bitcast.ll
Normal file
20
test/CodeGen/PowerPC/2012-10-12-bitcast.ll
Normal file
@ -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
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user