diff options
| author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-06-24 21:27:17 +0000 |
|---|---|---|
| committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-06-24 21:27:17 +0000 |
| commit | 709a6260157b925c19805679f69dea5f1e84e646 (patch) | |
| tree | 6096400137ead139582722ad930a91d3c9147ee7 | |
| parent | 91e6ba639912cc3fef05327c0273c8cce07d051b (diff) | |
| download | bcm5719-llvm-709a6260157b925c19805679f69dea5f1e84e646.tar.gz bcm5719-llvm-709a6260157b925c19805679f69dea5f1e84e646.zip | |
[Hexagon] Simplify (+fix) instruction selection for indexed loads/stores
llvm-svn: 273733
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 469 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Hexagon/vload-postinc-sel.ll | 52 |
2 files changed, 213 insertions, 308 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 1ddb9327776..b689d6c573d 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -94,11 +94,6 @@ public: void SelectLoad(SDNode *N); void SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl); void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl); - void SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, - const SDLoc &dl); - void SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, - const SDLoc &dl); - void SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl); void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl); void SelectStore(SDNode *N); void SelectSHL(SDNode *N); @@ -241,128 +236,11 @@ static bool doesIntrinsicReturnPredicate(unsigned ID) { } } -void HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, - unsigned Opcode, - const SDLoc &dl) { - SDValue Chain = LD->getChain(); - EVT LoadedVT = LD->getMemoryVT(); - SDValue Base = LD->getBasePtr(); - SDValue Offset = LD->getOffset(); - SDNode *OffsetNode = Offset.getNode(); - int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); - - if (HII->isValidAutoIncImm(LoadedVT, Val)) { - SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, - MVT::Other, Base, TargetConst, - Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, - SDValue(Result_1, 0)); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) }; - const SDValue Tos[] = { SDValue(Result_2, 0), - SDValue(Result_1, 1), - SDValue(Result_1, 2) }; - ReplaceUses(Froms, Tos, 3); - CurDAG->RemoveDeadNode(LD); - return; - } - - SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32); - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, - Base, TargetConst0, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, - SDValue(Result_1, 0)); - SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, - Base, TargetConstVal, - SDValue(Result_1, 1)); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) }; - const SDValue Tos[] = { SDValue(Result_2, 0), - SDValue(Result_3, 0), - SDValue(Result_1, 1) }; - ReplaceUses(Froms, Tos, 3); - CurDAG->RemoveDeadNode(LD); -} - -void HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, - unsigned Opcode, - const SDLoc &dl) { - SDValue Chain = LD->getChain(); - EVT LoadedVT = LD->getMemoryVT(); - SDValue Base = LD->getBasePtr(); - SDValue Offset = LD->getOffset(); - SDNode *OffsetNode = Offset.getNode(); - int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); - - if (HII->isValidAutoIncImm(LoadedVT, Val)) { - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, - MVT::i32, MVT::Other, Base, - TargetConstVal, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl, - MVT::i64, MVT::Other, - TargetConst0, - SDValue(Result_1,0)); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) }; - const SDValue Tos[] = { SDValue(Result_2, 0), - SDValue(Result_1, 1), - SDValue(Result_1, 2) }; - ReplaceUses(Froms, Tos, 3); - CurDAG->RemoveDeadNode(LD); - return; - } - - // Generate an indirect load. - SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32); - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, - MVT::Other, Base, TargetConst0, - Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl, - MVT::i64, MVT::Other, - TargetConst0, - SDValue(Result_1,0)); - // Add offset to base. - SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, - Base, TargetConstVal, - SDValue(Result_1, 1)); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) }; - const SDValue Tos[] = { SDValue(Result_2, 0), // Load value. - SDValue(Result_3, 0), // New address. - SDValue(Result_1, 1) }; - ReplaceUses(Froms, Tos, 3); - CurDAG->RemoveDeadNode(LD); - return; -} - void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) { SDValue Chain = LD->getChain(); SDValue Base = LD->getBasePtr(); SDValue Offset = LD->getOffset(); - SDNode *OffsetNode = Offset.getNode(); - // Get the constant value. - int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + int32_t Inc = cast<ConstantSDNode>(Offset.getNode())->getSExtValue(); EVT LoadedVT = LD->getMemoryVT(); unsigned Opcode = 0; @@ -370,119 +248,110 @@ void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) { // loads. ISD::LoadExtType ExtType = LD->getExtensionType(); bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD); - bool HasVecOffset = false; + bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc); - // Figure out the opcode. - if (LoadedVT == MVT::i64) { - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::L2_loadrd_pi; - else - Opcode = Hexagon::L2_loadrd_io; - } else if (LoadedVT == MVT::i32) { - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::L2_loadri_pi; + assert(LoadedVT.isSimple()); + switch (LoadedVT.getSimpleVT().SimpleTy) { + case MVT::i8: + if (IsZeroExt) + Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io; else - Opcode = Hexagon::L2_loadri_io; - } else if (LoadedVT == MVT::i16) { - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi; - else - Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io; - } else if (LoadedVT == MVT::i8) { - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi; + Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io; + break; + case MVT::i16: + if (IsZeroExt) + Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io; else - Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io; - } else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 || - LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) { - HasVecOffset = true; - bool Aligned = isAlignedMemNode(LD); - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Aligned ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32Ub_pi; + Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io; + break; + case MVT::i32: + Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io; + break; + case MVT::i64: + Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io; + break; + // 64B + case MVT::v64i8: + case MVT::v32i16: + case MVT::v16i32: + case MVT::v8i64: + if (isAlignedMemNode(LD)) + Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai; else - Opcode = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai; + Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai; + break; // 128B - } else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 || - LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) { - if (HST->useHVXOps()) { - bool Aligned = isAlignedMemNode(LD); - HasVecOffset = true; - if (HII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Aligned ? Hexagon::V6_vL32b_pi_128B - : Hexagon::V6_vL32Ub_pi_128B; - else - Opcode = Aligned ? Hexagon::V6_vL32b_ai_128B - : Hexagon::V6_vL32Ub_ai_128B; + case MVT::v128i8: + case MVT::v64i16: + case MVT::v32i32: + case MVT::v16i64: + if (isAlignedMemNode(LD)) + Opcode = IsValidInc ? Hexagon::V6_vL32b_pi_128B + : Hexagon::V6_vL32b_ai_128B; + else + Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi_128B + : Hexagon::V6_vL32Ub_ai_128B; + break; + default: + llvm_unreachable("Unexpected memory type in indexed load"); + } + + SDValue IncV = CurDAG->getTargetConstant(Inc, dl, MVT::i32); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + + auto getExt64 = [this,ExtType] (MachineSDNode *N, const SDLoc &dl) + -> MachineSDNode* { + if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD) { + SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32); + return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64, + Zero, SDValue(N, 0)); } - } else - llvm_unreachable("unknown memory type"); + if (ExtType == ISD::SEXTLOAD) + return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, + SDValue(N, 0)); + return N; + }; - // For zero extended i64 loads, we need to add combine instructions. - if (LD->getValueType(0) == MVT::i64 && IsZeroExt) { - SelectIndexedLoadZeroExtend64(LD, Opcode, dl); - return; - } - // Handle sign extended i64 loads. - if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD) { - SelectIndexedLoadSignExtend64(LD, Opcode, dl); - return; + // Loaded value Next address Chain + SDValue From[3] = { SDValue(LD,0), SDValue(LD,1), SDValue(LD,2) }; + SDValue To[3]; + + EVT ValueVT = LD->getValueType(0); + if (ValueVT == MVT::i64 && ExtType != ISD::NON_EXTLOAD) { + // A load extending to i64 will actually produce i32, which will then + // need to be extended to i64. + assert(LoadedVT.getSizeInBits() <= 32); + ValueVT = MVT::i32; } - if (HII->isValidAutoIncImm(LoadedVT, Val)) { - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode* Result = CurDAG->getMachineNode(Opcode, dl, - LD->getValueType(0), - MVT::i32, MVT::Other, Base, - TargetConstVal, Chain); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); - if (HasVecOffset) { - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 2) - }; - const SDValue Tos[] = { SDValue(Result, 0), - SDValue(Result, 2) - }; - ReplaceUses(Froms, Tos, 2); - } else { - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) - }; - const SDValue Tos[] = { SDValue(Result, 0), - SDValue(Result, 1), - SDValue(Result, 2) - }; - ReplaceUses(Froms, Tos, 3); - } - CurDAG->RemoveDeadNode(LD); - return; + if (IsValidInc) { + MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, + MVT::i32, MVT::Other, Base, + IncV, Chain); + L->setMemRefs(MemOp, MemOp+1); + To[1] = SDValue(L, 1); // Next address. + To[2] = SDValue(L, 2); // Chain. + // Handle special case for extension to i64. + if (LD->getValueType(0) == MVT::i64) + L = getExt64(L, dl); + To[0] = SDValue(L, 0); // Loaded (extended) value. } else { - SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32); - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, - LD->getValueType(0), - MVT::Other, Base, TargetConst0, - Chain); - SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, - Base, TargetConstVal, - SDValue(Result_1, 1)); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = LD->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - const SDValue Froms[] = { SDValue(LD, 0), - SDValue(LD, 1), - SDValue(LD, 2) - }; - const SDValue Tos[] = { SDValue(Result_1, 0), - SDValue(Result_2, 0), - SDValue(Result_1, 1) - }; - ReplaceUses(Froms, Tos, 3); - CurDAG->RemoveDeadNode(LD); - return; + SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32); + MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other, + Base, Zero, Chain); + L->setMemRefs(MemOp, MemOp+1); + To[2] = SDValue(L, 1); // Chain. + MachineSDNode *A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, + Base, IncV); + To[1] = SDValue(A, 0); // Next address. + // Handle special case for extension to i64. + if (LD->getValueType(0) == MVT::i64) + L = getExt64(L, dl); + To[0] = SDValue(L, 0); // Loaded (extended) value. } + ReplaceUses(From, To, 3); + CurDAG->RemoveDeadNode(LD); } @@ -644,7 +513,6 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) { return false; } - void HexagonDAGToDAGISel::SelectLoad(SDNode *N) { SDLoc dl(N); LoadSDNode *LD = cast<LoadSDNode>(N); @@ -668,104 +536,89 @@ void HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl) { SDValue Base = ST->getBasePtr(); SDValue Offset = ST->getOffset(); SDValue Value = ST->getValue(); - SDNode *OffsetNode = Offset.getNode(); // Get the constant value. - int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + int32_t Inc = cast<ConstantSDNode>(Offset.getNode())->getSExtValue(); EVT StoredVT = ST->getMemoryVT(); EVT ValueVT = Value.getValueType(); - // Offset value must be within representable range - // and must have correct alignment properties. - if (HII->isValidAutoIncImm(StoredVT, Val)) { - unsigned Opcode = 0; - - // Figure out the post inc version of opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi; - else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi; - else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi; - else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi; - else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 || - StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) { - if (isAlignedMemNode(ST)) - Opcode = Hexagon::V6_vS32b_pi; - else - Opcode = Hexagon::V6_vS32Ub_pi; - } - // 128B - else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 || - StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) { - if (HST->useHVXOps()) - Opcode = isAlignedMemNode(ST) ? Hexagon::V6_vS32b_pi_128B - : Hexagon::V6_vS32Ub_pi_128B; - } else - llvm_unreachable("unknown memory type"); - - if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) { - assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store"); - Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, - dl, MVT::i32, Value); - } - SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, dl, MVT::i32), Value, - Chain}; - // Build post increment store. - SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, - MVT::Other, Ops); - MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); - MemOp[0] = ST->getMemOperand(); - cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); - - ReplaceUses(ST, Result); - ReplaceUses(SDValue(ST,1), SDValue(Result,1)); - CurDAG->RemoveDeadNode(ST); - return; - } - - // Note: Order of operands matches the def of instruction: - // def S2_storerd_io - // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ... - // and it differs for POST_ST* for instance. - SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, dl, MVT::i32), Value, - Chain}; + bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc); unsigned Opcode = 0; - // Figure out the opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io; - else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io; - else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io; - else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io; - else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 || - StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) { + assert(StoredVT.isSimple()); + switch (StoredVT.getSimpleVT().SimpleTy) { + case MVT::i8: + Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io; + break; + case MVT::i16: + Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io; + break; + case MVT::i32: + Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io; + break; + case MVT::i64: + Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io; + break; + // 64B + case MVT::v64i8: + case MVT::v32i16: + case MVT::v16i32: + case MVT::v8i64: if (isAlignedMemNode(ST)) - Opcode = Hexagon::V6_vS32b_ai; + Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai; else - Opcode = Hexagon::V6_vS32Ub_ai; - } + Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai; + break; // 128B - else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 || - StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) { + case MVT::v128i8: + case MVT::v64i16: + case MVT::v32i32: + case MVT::v16i64: if (isAlignedMemNode(ST)) - Opcode = Hexagon::V6_vS32b_ai_128B; + Opcode = IsValidInc ? Hexagon::V6_vS32b_pi_128B + : Hexagon::V6_vS32b_ai_128B; else - Opcode = Hexagon::V6_vS32Ub_ai_128B; + Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi_128B + : Hexagon::V6_vS32Ub_ai_128B; + break; + default: + llvm_unreachable("Unexpected memory type in indexed store"); + } + + if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) { + assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store"); + Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, + dl, MVT::i32, Value); } - else llvm_unreachable("unknown memory type"); - - // Build regular store. - SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32); - SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); - // Build splitted incriment instruction. - SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, - Base, - TargetConstVal, - SDValue(Result_1, 0)); + + SDValue IncV = CurDAG->getTargetConstant(Inc, dl, MVT::i32); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); - cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); - ReplaceUses(SDValue(ST,0), SDValue(Result_2,0)); - ReplaceUses(SDValue(ST,1), SDValue(Result_1,0)); + // Next address Chain + SDValue From[2] = { SDValue(ST,0), SDValue(ST,1) }; + SDValue To[2]; + + if (IsValidInc) { + // Build post increment store. + SDValue Ops[] = { Base, IncV, Value, Chain }; + MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, + Ops); + S->setMemRefs(MemOp, MemOp + 1); + To[0] = SDValue(S, 0); + To[1] = SDValue(S, 1); + } else { + SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32); + SDValue Ops[] = { Base, Zero, Value, Chain }; + MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); + S->setMemRefs(MemOp, MemOp + 1); + To[1] = SDValue(S, 0); + MachineSDNode *A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, + Base, IncV); + To[0] = SDValue(A, 0); + } + + ReplaceUses(From, To, 2); CurDAG->RemoveDeadNode(ST); - return; } void HexagonDAGToDAGISel::SelectStore(SDNode *N) { diff --git a/llvm/test/CodeGen/Hexagon/vload-postinc-sel.ll b/llvm/test/CodeGen/Hexagon/vload-postinc-sel.ll new file mode 100644 index 00000000000..70ed3a9b1e8 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/vload-postinc-sel.ll @@ -0,0 +1,52 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s +; CHECK: = vmem(r{{[0-9]+}}++#1) + +target triple = "hexagon-unknown--elf" + +declare <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32>) #0 +declare <64 x i32> @llvm.hexagon.V6.vcombine.128B(<32 x i32>, <32 x i32>) #0 +declare <64 x i32> @llvm.hexagon.V6.vzb.128B(<32 x i32>) #0 +declare <32 x i32> @llvm.hexagon.V6.vsathub.128B(<32 x i32>, <32 x i32>) #0 +declare <64 x i32> @llvm.hexagon.V6.vaddh.dv.128B(<64 x i32>, <64 x i32>) #0 +declare <64 x i32> @llvm.hexagon.V6.vadduhsat.dv.128B(<64 x i32>, <64 x i32>) #0 +declare <32 x i32> @llvm.hexagon.V6.vabsdiffuh.128B(<32 x i32>, <32 x i32>) #0 + +define void @fred() #1 { +entry: + br i1 undef, label %b1, label %call_destructor.exit + +b1: ; preds = %entry + br label %b2 + +b2: ; preds = %b1, %b2 + %c2.host32.sroa.3.0 = phi <128 x i8> [ %5, %b2 ], [ undef, %b1 ] + %sobel_halide.s0.x.x = phi i32 [ %17, %b2 ], [ 0, %b1 ] + %0 = add nsw i32 %sobel_halide.s0.x.x, undef + %1 = shl i32 %0, 7 + %2 = add nsw i32 %1, 128 + %3 = getelementptr inbounds i8, i8* undef, i32 %2 + %4 = bitcast i8* %3 to <128 x i8>* + %5 = load <128 x i8>, <128 x i8>* %4, align 128 + %6 = bitcast <128 x i8> %c2.host32.sroa.3.0 to <32 x i32> + %7 = tail call <32 x i32> @llvm.hexagon.V6.valignbi.128B(<32 x i32> undef, <32 x i32> %6, i32 1) + %8 = tail call <64 x i32> @llvm.hexagon.V6.vzb.128B(<32 x i32> %7) #1 + %9 = tail call <64 x i32> @llvm.hexagon.V6.vadduhsat.dv.128B(<64 x i32> undef, <64 x i32> %8) #1 + %10 = tail call <64 x i32> @llvm.hexagon.V6.vadduhsat.dv.128B(<64 x i32> %9, <64 x i32> undef) #1 + %11 = tail call <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32> %10) + %12 = tail call <32 x i32> @llvm.hexagon.V6.vabsdiffuh.128B(<32 x i32> undef, <32 x i32> %11) #1 + %13 = tail call <64 x i32> @llvm.hexagon.V6.vcombine.128B(<32 x i32> %12, <32 x i32> undef) + %14 = tail call <64 x i32> @llvm.hexagon.V6.vaddh.dv.128B(<64 x i32> undef, <64 x i32> %13) #1 + %15 = tail call <32 x i32> @llvm.hexagon.V6.hi.128B(<64 x i32> %14) #1 + %16 = tail call <32 x i32> @llvm.hexagon.V6.vsathub.128B(<32 x i32> %15, <32 x i32> undef) #1 + store <32 x i32> %16, <32 x i32>* undef, align 128 + %17 = add nuw nsw i32 %sobel_halide.s0.x.x, 1 + br label %b2 + +call_destructor.exit: ; preds = %entry + ret void +} + +declare <32 x i32> @llvm.hexagon.V6.valignbi.128B(<32 x i32>, <32 x i32>, i32) #0 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,+hvx-double" } |

