Index: llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -337,8 +337,21 @@ // The input is widened to the same size. Convert to the widened value. // Make sure that the outgoing value is not a vector, because this would // make us bitcast between two vectors which are legalized in different ways. - if (NOutVT.bitsEq(NInVT) && !NOutVT.isVector()) - return DAG.getNode(ISD::BITCAST, dl, NOutVT, GetWidenedVector(InOp)); + if (NOutVT.bitsEq(NInVT) && !NOutVT.isVector()) { + SDValue Res = + DAG.getNode(ISD::BITCAST, dl, NOutVT, GetWidenedVector(InOp)); + + // For big endian targets we need to shift the casted value or the + // interesting bits will end up at the wrong place. + if (DAG.getDataLayout().isBigEndian()) { + unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits(); + EVT ShiftAmtTy = TLI.getShiftAmountTy(NOutVT, DAG.getDataLayout()); + assert(ShiftAmt < NOutVT.getSizeInBits() && "Too large shift amount!"); + Res = DAG.getNode(ISD::SRL, dl, NOutVT, Res, + DAG.getConstant(ShiftAmt, dl, ShiftAmtTy)); + } + return Res; + } // If the output type is also a vector and widening it to the same size // as the widened input type would be a legal type, we can widen the bitcast // and handle the promotion after. Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -3457,7 +3457,7 @@ switch (getTypeAction(InVT)) { case TargetLowering::TypeLegal: break; - case TargetLowering::TypePromoteInteger: + case TargetLowering::TypePromoteInteger: { // If the incoming type is a vector that is being promoted, then // we know that the elements are arranged differently and that we // must perform the conversion using a stack slot. @@ -3466,11 +3466,24 @@ // If the InOp is promoted to the same size, convert it. Otherwise, // fall out of the switch and widen the promoted input. - InOp = GetPromotedInteger(InOp); - InVT = InOp.getValueType(); - if (WidenVT.bitsEq(InVT)) - return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp); + SDValue NInOp = GetPromotedInteger(InOp); + EVT NInVT = NInOp.getValueType(); + if (WidenVT.bitsEq(NInVT)) { + // For big endian targets we need to shift the input integer or the + // interesting bits will end up at the wrong place. + if (DAG.getDataLayout().isBigEndian()) { + unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits(); + EVT ShiftAmtTy = TLI.getShiftAmountTy(NInVT, DAG.getDataLayout()); + assert(ShiftAmt < WidenVT.getSizeInBits() && "Too large shift amount!"); + NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp, + DAG.getConstant(ShiftAmt, dl, ShiftAmtTy)); + } + return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp); + } + InOp = NInOp; + InVT = NInVT; break; + } case TargetLowering::TypeSoftenFloat: case TargetLowering::TypePromoteFloat: case TargetLowering::TypeExpandInteger: Index: llvm/test/CodeGen/ARM/legalize-bitcast.ll =================================================================== --- llvm/test/CodeGen/ARM/legalize-bitcast.ll +++ llvm/test/CodeGen/ARM/legalize-bitcast.ll @@ -24,7 +24,7 @@ ; CHECK-NEXT: vldmia sp, {d16, d17} @ 16-byte Reload ; CHECK-NEXT: vrev32.16 q9, q8 ; CHECK-NEXT: @ kill: def $d19 killed $d19 killed $q9 -; CHECK-NEXT: vmov.32 r0, d19[1] +; CHECK-NEXT: vmov.32 r0, d19[0] ; CHECK-NEXT: add sp, sp, #28 ; CHECK-NEXT: pop {r4} ; CHECK-NEXT: bx lr @@ -41,14 +41,17 @@ define i16 @int_to_vec(i80 %in) { ; CHECK-LABEL: int_to_vec: ; CHECK: @ %bb.0: -; CHECK-NEXT: sub sp, sp, #4 -; CHECK-NEXT: vmov.i32 q8, #0x0 -; CHECK-NEXT: vrev32.16 q8, q8 -; CHECK-NEXT: @ kill: def $d16 killed $d16 killed $q8 -; CHECK-NEXT: vmov.u16 r3, d16[0] -; CHECK-NEXT: str r0, [sp] @ 4-byte Spill -; CHECK-NEXT: mov r0, r3 -; CHECK-NEXT: add sp, sp, #4 +; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: mov r12, r0 +; CHECK-NEXT: lsl r0, r0, #16 +; CHECK-NEXT: orr r0, r0, r1, lsr #16 +; CHECK-NEXT: @ implicit-def: $d16 +; CHECK-NEXT: vmov.32 d16[0], r0 +; CHECK-NEXT: @ implicit-def: $q9 +; CHECK-NEXT: vmov.f64 d18, d16 +; CHECK-NEXT: vrev32.16 q9, q9 +; CHECK-NEXT: @ kill: def $d18 killed $d18 killed $q9 +; CHECK-NEXT: vmov.u16 r0, d18[0] ; CHECK-NEXT: bx lr %vec = bitcast i80 %in to <5 x i16> %e0 = extractelement <5 x i16> %vec, i32 0