[Hexagon] Extend OptAddrMode pass to vgather

This change extends the addressing mode optimization
pass to HVX vgather. This is specifically intended to
resolve compiler not generating indexed addresses for
vgather stores to vtcm. Changed the vgather pseudo
instructions to accept an immediate operand and handled
addition of appropriate immediate operand in addressing
mode optimization pass.
This commit is contained in:
Shubham Pawar 2019-06-19 11:38:06 -05:00 committed by Krzysztof Parzyszek
parent de731efd4c
commit 41085357df
7 changed files with 234 additions and 54 deletions

View File

@ -2393,6 +2393,7 @@ void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) {
SDValue Base = N->getOperand(4);
SDValue Modifier = N->getOperand(5);
SDValue Offset = N->getOperand(6);
SDValue ImmOperand = CurDAG->getTargetConstant(0, dl, MVT::i32);
unsigned Opcode;
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
@ -2414,7 +2415,8 @@ void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) {
}
SDVTList VTs = CurDAG->getVTList(MVT::Other);
SDValue Ops[] = { Address, Predicate, Base, Modifier, Offset, Chain };
SDValue Ops[] = { Address, ImmOperand,
Predicate, Base, Modifier, Offset, Chain };
SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);
MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
@ -2430,6 +2432,7 @@ void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) {
SDValue Base = N->getOperand(3);
SDValue Modifier = N->getOperand(4);
SDValue Offset = N->getOperand(5);
SDValue ImmOperand = CurDAG->getTargetConstant(0, dl, MVT::i32);
unsigned Opcode;
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
@ -2451,7 +2454,7 @@ void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) {
}
SDVTList VTs = CurDAG->getVTList(MVT::Other);
SDValue Ops[] = { Address, Base, Modifier, Offset, Chain };
SDValue Ops[] = { Address, ImmOperand, Base, Modifier, Offset, Chain };
SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);
MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();

View File

@ -1506,75 +1506,75 @@ HexagonInstrInfo::expandVGatherPseudo(MachineInstr &MI) const {
switch (Opc) {
case Hexagon::V6_vgathermh_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
case Hexagon::V6_vgathermw_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
case Hexagon::V6_vgathermhw_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
case Hexagon::V6_vgathermhq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
case Hexagon::V6_vgathermwq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
case Hexagon::V6_vgathermhwq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
@ -2767,7 +2767,13 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::V6_vL32b_nt_ai:
case Hexagon::V6_vS32b_nt_ai:
case Hexagon::V6_vL32Ub_ai:
case Hexagon::V6_vS32Ub_ai: {
case Hexagon::V6_vS32Ub_ai:
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo: {
unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass);
assert(isPowerOf2_32(VectorSize));
if (Offset & (VectorSize-1))

View File

@ -110,6 +110,8 @@ private:
bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
const MachineOperand &ImmOp, unsigned ImmOpNum);
bool isValidOffset(MachineInstr *MI, int Offset);
unsigned getBaseOpPosition(MachineInstr *MI);
unsigned getOffsetOpPosition(MachineInstr *MI);
};
} // end anonymous namespace
@ -322,6 +324,25 @@ bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,
}
bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
if (HII->isHVXVec(*MI)) {
// only HVX vgather instructions handled
// TODO: extend the pass to other vector load/store operations
switch (MI->getOpcode()) {
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
default:
return false;
}
}
if (HII->getAddrMode(*MI) != HexagonII::BaseImmOffset)
return false;
unsigned AlignMask = 0;
switch (HII->getMemAccessSize(*MI)) {
case HexagonII::MemAccessSize::DoubleWordAccess:
@ -345,29 +366,62 @@ bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
}
unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {
const MCInstrDesc &MID = MI->getDesc();
switch (MI->getOpcode()) {
// vgather pseudos are mayLoad and mayStore
// hence need to explicitly specify Base and
// Offset operand positions
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return 0;
default:
return MID.mayLoad() ? 1 : 0;
}
}
unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {
const MCInstrDesc &MID = MI->getDesc();
switch (MI->getOpcode()) {
// vgather pseudos are mayLoad and mayStore
// hence need to explicitly specify Base and
// Offset operand positions
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return 1;
default:
return MID.mayLoad() ? 2 : 1;
}
}
bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
MachineInstr *AddMI,
const NodeList &UNodeList) {
Register AddDefR = AddMI->getOperand(0).getReg();
Register BaseReg = AddMI->getOperand(1).getReg();
for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
NodeAddr<UseNode *> UN = *I;
NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
MachineInstr *MI = SN.Addr->getCode();
const MCInstrDesc &MID = MI->getDesc();
if ((!MID.mayLoad() && !MID.mayStore()) ||
HII->getAddrMode(*MI) != HexagonII::BaseImmOffset ||
HII->isHVXVec(*MI))
return false;
if ((!MID.mayLoad() && !MID.mayStore()))
return false;
MachineOperand BaseOp = MID.mayLoad() ? MI->getOperand(1)
: MI->getOperand(0);
MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));
if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)
return false;
MachineOperand OffsetOp = MID.mayLoad() ? MI->getOperand(2)
: MI->getOperand(1);
MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));
if (!OffsetOp.isImm())
return false;
@ -382,11 +436,19 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
// Ex: Rx= add(Rt,#10)
// memw(Rx+#0) = Rs
// will be replaced with => memw(Rt+#10) = Rs
Register BaseReg = AddMI->getOperand(1).getReg();
if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
return false;
}
NodeId LRExtRegRD = 0;
// Iterate through all the UseNodes in SN and find the reaching def
// for the LRExtReg.
for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
RegisterRef RR = UA.Addr->getRegRef(*DFG);
if (BaseReg == RR.Reg)
LRExtRegRD = UA.Addr->getReachingDef();
}
// Update all the uses of 'add' with the appropriate base and offset
// values.
bool Changed = false;
@ -400,6 +462,12 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
<< ">]: " << *UseMI << "\n");
Changed |= updateAddUses(AddMI, UseMI);
// Set the reachingDef for UseNode under consideration
// after updating the Add use. This local change is
// to avoid rebuilding of the RDF graph after update.
NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);
}
if (Changed)
@ -409,21 +477,18 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
}
bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,
MachineInstr *UseMI) {
MachineInstr *UseMI) {
const MachineOperand ImmOp = AddMI->getOperand(2);
const MachineOperand AddRegOp = AddMI->getOperand(1);
Register newReg = AddRegOp.getReg();
const MCInstrDesc &MID = UseMI->getDesc();
Register NewReg = AddRegOp.getReg();
MachineOperand &BaseOp = MID.mayLoad() ? UseMI->getOperand(1)
: UseMI->getOperand(0);
MachineOperand &OffsetOp = MID.mayLoad() ? UseMI->getOperand(2)
: UseMI->getOperand(1);
BaseOp.setReg(newReg);
MachineOperand &BaseOp = UseMI->getOperand(getBaseOpPosition(UseMI));
MachineOperand &OffsetOp = UseMI->getOperand(getOffsetOpPosition(UseMI));
BaseOp.setReg(NewReg);
BaseOp.setIsUndef(AddRegOp.isUndef());
BaseOp.setImplicit(AddRegOp.isImplicit());
OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm());
MRI->clearKillFlags(newReg);
MRI->clearKillFlags(NewReg);
return true;
}

View File

@ -9,8 +9,8 @@
multiclass vgathermh<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}
@ -18,8 +18,8 @@ multiclass vgathermh<RegisterClass RC> {
multiclass vgathermw<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}
@ -27,8 +27,8 @@ multiclass vgathermw<RegisterClass RC> {
multiclass vgathermhw<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}
@ -40,8 +40,9 @@ defm V6_vgathermhw_pseudo : vgathermhw<HvxWR>;
multiclass vgathermhq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}
@ -49,8 +50,9 @@ multiclass vgathermhq<RegisterClass RC1, RegisterClass RC2> {
multiclass vgathermwq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}
@ -58,8 +60,9 @@ multiclass vgathermwq<RegisterClass RC1, RegisterClass RC2> {
multiclass vgathermhwq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}

View File

@ -15,8 +15,8 @@ body: |
bb.0:
liveins: $r0, $r1, $r2, $r3, $m0, $v0, $v1, $v2
$v0 = V6_vaslw_acc $v0, killed $v1, $r0
V6_vgathermw_pseudo $r1, $r2, $m0, killed $v2
V6_vgathermw_pseudo $r1, 0, $r2, $m0, killed $v2
$r4 = A2_addi $r1, 512
$r5 = A2_addi $r1, 640
V6_vgathermw_pseudo killed $r3, $r2, $m0, killed $v0
V6_vgathermw_pseudo killed $r3, 0, $r2, $m0, killed $v0
...

View File

@ -0,0 +1,103 @@
; RUN: llc -march=hexagon -O3 -disable-hexagon-amodeopt < %s | FileCheck %s --check-prefix=CHECK-NO-AMODE
; RUN: llc -march=hexagon -O3 < %s | FileCheck %s --check-prefix=CHECK-AMODE
; CHECK-NO-AMODE: [[REG1:(r[0-9]+)]] = add({{r[0-9]+}},#0)
; CHECK-NO-AMODE: [[REG2:(r[0-9]+)]] = add([[REG1]],#128)
; CHECK-NO-AMODE: [[REG3:(r[0-9]+)]] = add([[REG1]],#256)
; CHECK-NO-AMODE: [[REG4:(r[0-9]+)]] = add([[REG1]],#384)
; CHECK-NO-AMODE: [[REG5:(r[0-9]+)]] = add([[REG1]],#512)
; CHECK-NO-AMODE: [[REG6:(r[0-9]+)]] = add([[REG1]],#640)
; CHECK-NO-AMODE: vmem([[REG1]]+#0) = vtmp.new
; CHECK-NO-AMODE: vmem([[REG2]]+#0) = vtmp.new
; CHECK-NO-AMODE: vmem([[REG3]]+#0) = vtmp.new
; CHECK-NO-AMODE: vmem([[REG4]]+#0) = vtmp.new
; CHECK-NO-AMODE: vmem([[REG5]]+#0) = vtmp.new
; CHECK-NO-AMODE: vmem([[REG6]]+#0) = vtmp.new
; CHECK-AMODE: [[REG1:(r[0-9]+)]] = add({{r[0-9]+}},#0)
; CHECK-AMODE-NOT: {{r[0-9]+}} = add([[REG1]],{{[0-9]+}})
; CHECK-AMODE: vmem([[REG1]]+#0) = vtmp.new
; CHECK-AMODE: vmem([[REG1]]+#1) = vtmp.new
; CHECK-AMODE: vmem([[REG1]]+#2) = vtmp.new
; CHECK-AMODE: vmem([[REG1]]+#3) = vtmp.new
; CHECK-AMODE: vmem([[REG1]]+#4) = vtmp.new
; CHECK-AMODE: vmem([[REG1]]+#5) = vtmp.new
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon"
; Function Attrs: nounwind readnone
define dso_local void @contiguos_vgather_test(i32 %Rb, i32 %mu, i32 %nloops, <32 x i32> %Vv, <64 x i32> %Vvv, <32 x i32> %Qs) local_unnamed_addr #0 {
entry:
%Vout1 = alloca <32 x i32>, align 128
%0 = bitcast <32 x i32>* %Vout1 to i8*
call void @llvm.lifetime.start.p0i8(i64 128, i8* nonnull %0) #2
%cmp23 = icmp sgt i32 %nloops, 0
br i1 %cmp23, label %for.body.lr.ph, label %for.cond.cleanup
for.body.lr.ph: ; preds = %entry
%add.ptr = getelementptr inbounds <32 x i32>, <32 x i32>* %Vout1, i32 1
%1 = bitcast <32 x i32>* %add.ptr to i8*
%add.ptr1 = getelementptr inbounds <32 x i32>, <32 x i32>* %Vout1, i32 2
%2 = bitcast <32 x i32>* %add.ptr1 to i8*
%add.ptr2 = getelementptr inbounds <32 x i32>, <32 x i32>* %Vout1, i32 3
%3 = bitcast <32 x i32>* %add.ptr2 to i8*
%4 = tail call <128 x i1> @llvm.hexagon.V6.vandvrt.128B(<32 x i32> %Qs, i32 -1)
%add.ptr3 = getelementptr inbounds <32 x i32>, <32 x i32>* %Vout1, i32 4
%5 = bitcast <32 x i32>* %add.ptr3 to i8*
%add.ptr4 = getelementptr inbounds <32 x i32>, <32 x i32>* %Vout1, i32 5
%6 = bitcast <32 x i32>* %add.ptr4 to i8*
br label %for.body
for.cond.cleanup: ; preds = %for.body, %entry
call void @llvm.lifetime.end.p0i8(i64 128, i8* nonnull %0) #2
ret void
for.body: ; preds = %for.body, %for.body.lr.ph
%i.024 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
call void @llvm.hexagon.V6.vgathermh.128B(i8* nonnull %0, i32 %Rb, i32 %mu, <32 x i32> %Vv)
call void @llvm.hexagon.V6.vgathermw.128B(i8* nonnull %1, i32 %Rb, i32 %mu, <32 x i32> %Vv)
call void @llvm.hexagon.V6.vgathermhw.128B(i8* nonnull %2, i32 %Rb, i32 %mu, <64 x i32> %Vvv)
call void @llvm.hexagon.V6.vgathermhq.128B(i8* nonnull %3, <128 x i1> %4, i32 %Rb, i32 %mu, <32 x i32> %Vv)
call void @llvm.hexagon.V6.vgathermwq.128B(i8* nonnull %5, <128 x i1> %4, i32 %Rb, i32 %mu, <32 x i32> %Vv)
call void @llvm.hexagon.V6.vgathermhwq.128B(i8* nonnull %6, <128 x i1> %4, i32 %Rb, i32 %mu, <64 x i32> %Vvv)
%inc = add nuw nsw i32 %i.024, 1
%exitcond = icmp eq i32 %inc, %nloops
br i1 %exitcond, label %for.cond.cleanup, label %for.body
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermh.128B(i8*, i32, i32, <32 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermw.128B(i8*, i32, i32, <32 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermhw.128B(i8*, i32, i32, <64 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermhq.128B(i8*, <128 x i1>, i32, i32, <32 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermwq.128B(i8*, <128 x i1>, i32, i32, <32 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.hexagon.V6.vgathermhwq.128B(i8*, <128 x i1>, i32, i32, <64 x i32>) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
declare <128 x i1> @llvm.hexagon.V6.vandvrt.128B(<32 x i32>, i32) #1
attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv65" "target-features"="+hvx-length128b,+hvxv65,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
attributes #2 = { nounwind }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"wchar_size", i32 4}

View File

@ -21,7 +21,7 @@ body: |
bb.1:
liveins: $r0, $r1, $r2, $m0, $w0
$r1 = A2_addi $r1, 1
V6_vgathermhw_pseudo $r0, $r2, $m0, $w0, implicit-def $vtmp
V6_vgathermhw_pseudo killed $r0, 0, killed $r2, killed $m0, killed $w0, implicit-def $vtmp
ENDLOOP0 %bb.1, implicit $lc0, implicit $sa0, implicit-def $lc0, implicit-def $p3, implicit-def $pc, implicit-def $usr
bb.2: