diff --git a/lib/Target/R600/SIISelLowering.cpp b/lib/Target/R600/SIISelLowering.cpp index be42ceb52d9..1a73d9bda58 100644 --- a/lib/Target/R600/SIISelLowering.cpp +++ b/lib/Target/R600/SIISelLowering.cpp @@ -1920,6 +1920,30 @@ void SITargetLowering::adjustWritemask(MachineSDNode *&Node, } } +/// \brief Legalize INSERT_SUBREG instructions with frame index operands. +/// LLVM assumes that all INSERT_SUBREG inputs are registers. +static void legalizeInsertSubreg(MachineSDNode *InsertSubreg, + SelectionDAG &DAG) { + + assert(InsertSubreg->getMachineOpcode() == AMDGPU::INSERT_SUBREG); + + SmallVector Ops; + for (unsigned i = 0; i < 2; ++i) { + if (!isa(InsertSubreg->getOperand(i))) { + Ops.push_back(InsertSubreg->getOperand(i)); + continue; + } + + SDLoc DL(InsertSubreg); + Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, + InsertSubreg->getOperand(i).getValueType(), + InsertSubreg->getOperand(i)), 0)); + } + + DAG.UpdateNodeOperands(InsertSubreg, Ops[0], Ops[1], + InsertSubreg->getOperand(2)); +} + /// \brief Fold the instructions after selecting them. SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node, SelectionDAG &DAG) const { @@ -1930,6 +1954,11 @@ SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node, if (TII->isMIMG(Node->getMachineOpcode())) adjustWritemask(Node, DAG); + if (Node->getMachineOpcode() == AMDGPU::INSERT_SUBREG) { + legalizeTargetIndependentNode(Node, DAG); + return Node; + } + return legalizeOperands(Node, DAG); } diff --git a/test/CodeGen/R600/insert_subreg.ll b/test/CodeGen/R600/insert_subreg.ll new file mode 100644 index 00000000000..e311e1953cf --- /dev/null +++ b/test/CodeGen/R600/insert_subreg.ll @@ -0,0 +1,15 @@ +; RUN: llc -march=r600 -mcpu=SI -mattr=-promote-alloca -verify-machineinstrs < %s + +; Test that INSERT_SUBREG instructions don't have non-register operands after +; instruction selection. + +; Make sure this doesn't crash +; CHECK-LABEL: test: +define void @test(i64 addrspace(1)* %out) { +entry: + %tmp0 = alloca [16 x i32] + %tmp1 = ptrtoint [16 x i32]* %tmp0 to i32 + %tmp2 = sext i32 %tmp1 to i64 + store i64 %tmp2, i64 addrspace(1)* %out + ret void +}