[llvm] r273733 - [Hexagon] Simplify (+fix) instruction selection for indexed loads/stores
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 24 14:27:17 PDT 2016
Author: kparzysz
Date: Fri Jun 24 16:27:17 2016
New Revision: 273733
URL: http://llvm.org/viewvc/llvm-project?rev=273733&view=rev
Log:
[Hexagon] Simplify (+fix) instruction selection for indexed loads/stores
Added:
llvm/trunk/test/CodeGen/Hexagon/vload-postinc-sel.ll
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp?rev=273733&r1=273732&r2=273733&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp Fri Jun 24 16:27:17 2016
@@ -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
}
}
-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::SelectIndexedL
// 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;
- 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;
+ assert(LoadedVT.isSimple());
+ switch (LoadedVT.getSimpleVT().SimpleTy) {
+ case MVT::i8:
+ if (IsZeroExt)
+ Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
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::tryLoadOfLoadI
return false;
}
-
void HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
SDLoc dl(N);
LoadSDNode *LD = cast<LoadSDNode>(N);
@@ -668,104 +536,89 @@ void HexagonDAGToDAGISel::SelectIndexedS
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");
}
- 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));
+ 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 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) {
Added: llvm/trunk/test/CodeGen/Hexagon/vload-postinc-sel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/vload-postinc-sel.ll?rev=273733&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/vload-postinc-sel.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/vload-postinc-sel.ll Fri Jun 24 16:27:17 2016
@@ -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" }
More information about the llvm-commits
mailing list