Skip to content

Commit 142787d

Browse files
[RISCV][VLOPT] Add support for checkUsers when UserMI is a Single-Width Integer Reduction (#120345)
Reductions are weird because for some operands, they are vector registers but only read the first lane. For these operands, we do not need to check to make sure the EEW and EMUL ratios match. The EEWs, however, do need to match.
1 parent b225513 commit 142787d

File tree

4 files changed

+215
-53
lines changed

4 files changed

+215
-53
lines changed

llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ class RISCVVLOptimizer : public MachineFunctionPass {
5050
StringRef getPassName() const override { return PASS_NAME; }
5151

5252
private:
53-
bool checkUsers(const MachineOperand *&CommonVL, MachineInstr &MI);
53+
std::optional<MachineOperand> getMinimumVLForUser(MachineOperand &UserOp);
54+
/// Returns the largest common VL MachineOperand that may be used to optimize
55+
/// MI. Returns std::nullopt if it failed to find a suitable VL.
56+
std::optional<MachineOperand> checkUsers(MachineInstr &MI);
5457
bool tryReduceVL(MachineInstr &MI);
5558
bool isCandidate(const MachineInstr &MI) const;
5659
};
@@ -95,6 +98,8 @@ struct OperandInfo {
9598
OperandInfo(std::pair<unsigned, bool> EMUL, unsigned Log2EEW)
9699
: S(State::Known), EMUL(EMUL), Log2EEW(Log2EEW) {}
97100

101+
OperandInfo(unsigned Log2EEW) : S(State::Known), Log2EEW(Log2EEW) {}
102+
98103
OperandInfo() : S(State::Unknown) {}
99104

100105
bool isUnknown() const { return S == State::Unknown; }
@@ -107,6 +112,11 @@ struct OperandInfo {
107112
A.EMUL->second == B.EMUL->second;
108113
}
109114

115+
static bool EEWAreEqual(const OperandInfo &A, const OperandInfo &B) {
116+
assert(A.isKnown() && B.isKnown() && "Both operands must be known");
117+
return A.Log2EEW == B.Log2EEW;
118+
}
119+
110120
void print(raw_ostream &OS) const {
111121
if (isUnknown()) {
112122
OS << "Unknown";
@@ -724,6 +734,23 @@ static OperandInfo getOperandInfo(const MachineOperand &MO,
724734
return OperandInfo(MIVLMul, MILog2SEW);
725735
}
726736

737+
// Vector Reduction Operations
738+
// Vector Single-Width Integer Reduction Instructions
739+
// The Dest and VS1 only read element 0 of the vector register. Return just
740+
// the EEW for these. VS2 has EEW=SEW and EMUL=LMUL.
741+
case RISCV::VREDAND_VS:
742+
case RISCV::VREDMAX_VS:
743+
case RISCV::VREDMAXU_VS:
744+
case RISCV::VREDMIN_VS:
745+
case RISCV::VREDMINU_VS:
746+
case RISCV::VREDOR_VS:
747+
case RISCV::VREDSUM_VS:
748+
case RISCV::VREDXOR_VS: {
749+
if (MO.getOperandNo() == 2)
750+
return OperandInfo(MIVLMul, MILog2SEW);
751+
return OperandInfo(MILog2SEW);
752+
}
753+
727754
default:
728755
return {};
729756
}
@@ -1061,79 +1088,102 @@ bool RISCVVLOptimizer::isCandidate(const MachineInstr &MI) const {
10611088
return true;
10621089
}
10631090

1064-
bool RISCVVLOptimizer::checkUsers(const MachineOperand *&CommonVL,
1065-
MachineInstr &MI) {
1091+
std::optional<MachineOperand>
1092+
RISCVVLOptimizer::getMinimumVLForUser(MachineOperand &UserOp) {
1093+
const MachineInstr &UserMI = *UserOp.getParent();
1094+
const MCInstrDesc &Desc = UserMI.getDesc();
1095+
1096+
if (!RISCVII::hasVLOp(Desc.TSFlags) || !RISCVII::hasSEWOp(Desc.TSFlags)) {
1097+
LLVM_DEBUG(dbgs() << " Abort due to lack of VL, assume that"
1098+
" use VLMAX\n");
1099+
return std::nullopt;
1100+
}
1101+
1102+
// Instructions like reductions may use a vector register as a scalar
1103+
// register. In this case, we should treat it as only reading the first lane.
1104+
if (isVectorOpUsedAsScalarOp(UserOp)) {
1105+
[[maybe_unused]] Register R = UserOp.getReg();
1106+
[[maybe_unused]] const TargetRegisterClass *RC = MRI->getRegClass(R);
1107+
assert(RISCV::VRRegClass.hasSubClassEq(RC) &&
1108+
"Expect LMUL 1 register class for vector as scalar operands!");
1109+
LLVM_DEBUG(dbgs() << " Used this operand as a scalar operand\n");
1110+
1111+
return MachineOperand::CreateImm(1);
1112+
}
1113+
1114+
unsigned VLOpNum = RISCVII::getVLOpNum(Desc);
1115+
const MachineOperand &VLOp = UserMI.getOperand(VLOpNum);
1116+
// Looking for an immediate or a register VL that isn't X0.
1117+
assert((!VLOp.isReg() || VLOp.getReg() != RISCV::X0) &&
1118+
"Did not expect X0 VL");
1119+
return VLOp;
1120+
}
1121+
1122+
std::optional<MachineOperand> RISCVVLOptimizer::checkUsers(MachineInstr &MI) {
10661123
// FIXME: Avoid visiting each user for each time we visit something on the
10671124
// worklist, combined with an extra visit from the outer loop. Restructure
10681125
// along lines of an instcombine style worklist which integrates the outer
10691126
// pass.
1070-
bool CanReduceVL = true;
1127+
std::optional<MachineOperand> CommonVL;
10711128
for (auto &UserOp : MRI->use_operands(MI.getOperand(0).getReg())) {
10721129
const MachineInstr &UserMI = *UserOp.getParent();
10731130
LLVM_DEBUG(dbgs() << " Checking user: " << UserMI << "\n");
1074-
1075-
// Instructions like reductions may use a vector register as a scalar
1076-
// register. In this case, we should treat it like a scalar register which
1077-
// does not impact the decision on whether to optimize VL.
1078-
// TODO: Treat it like a scalar register instead of bailing out.
1079-
if (isVectorOpUsedAsScalarOp(UserOp)) {
1080-
CanReduceVL = false;
1081-
break;
1082-
}
1083-
10841131
if (mayReadPastVL(UserMI)) {
10851132
LLVM_DEBUG(dbgs() << " Abort because used by unsafe instruction\n");
1086-
CanReduceVL = false;
1087-
break;
1133+
return std::nullopt;
10881134
}
10891135

10901136
// Tied operands might pass through.
10911137
if (UserOp.isTied()) {
10921138
LLVM_DEBUG(dbgs() << " Abort because user used as tied operand\n");
1093-
CanReduceVL = false;
1094-
break;
1139+
return std::nullopt;
10951140
}
10961141

1097-
const MCInstrDesc &Desc = UserMI.getDesc();
1098-
if (!RISCVII::hasVLOp(Desc.TSFlags) || !RISCVII::hasSEWOp(Desc.TSFlags)) {
1099-
LLVM_DEBUG(dbgs() << " Abort due to lack of VL or SEW, assume that"
1100-
" use VLMAX\n");
1101-
CanReduceVL = false;
1102-
break;
1103-
}
1104-
1105-
unsigned VLOpNum = RISCVII::getVLOpNum(Desc);
1106-
const MachineOperand &VLOp = UserMI.getOperand(VLOpNum);
1107-
1108-
// Looking for an immediate or a register VL that isn't X0.
1109-
assert((!VLOp.isReg() || VLOp.getReg() != RISCV::X0) &&
1110-
"Did not expect X0 VL");
1142+
auto VLOp = getMinimumVLForUser(UserOp);
1143+
if (!VLOp)
1144+
return std::nullopt;
11111145

11121146
// Use the largest VL among all the users. If we cannot determine this
11131147
// statically, then we cannot optimize the VL.
1114-
if (!CommonVL || RISCV::isVLKnownLE(*CommonVL, VLOp)) {
1115-
CommonVL = &VLOp;
1148+
if (!CommonVL || RISCV::isVLKnownLE(*CommonVL, *VLOp)) {
1149+
CommonVL = *VLOp;
11161150
LLVM_DEBUG(dbgs() << " User VL is: " << VLOp << "\n");
1117-
} else if (!RISCV::isVLKnownLE(VLOp, *CommonVL)) {
1151+
} else if (!RISCV::isVLKnownLE(*VLOp, *CommonVL)) {
11181152
LLVM_DEBUG(dbgs() << " Abort because cannot determine a common VL\n");
1119-
CanReduceVL = false;
1120-
break;
1153+
return std::nullopt;
1154+
}
1155+
1156+
if (!RISCVII::hasSEWOp(UserMI.getDesc().TSFlags)) {
1157+
LLVM_DEBUG(dbgs() << " Abort due to lack of SEW operand\n");
1158+
return std::nullopt;
11211159
}
11221160

1123-
// The SEW and LMUL of destination and source registers need to match.
11241161
OperandInfo ConsumerInfo = getOperandInfo(UserOp, MRI);
11251162
OperandInfo ProducerInfo = getOperandInfo(MI.getOperand(0), MRI);
1126-
if (ConsumerInfo.isUnknown() || ProducerInfo.isUnknown() ||
1127-
!OperandInfo::EMULAndEEWAreEqual(ConsumerInfo, ProducerInfo)) {
1128-
LLVM_DEBUG(dbgs() << " Abort due to incompatible or unknown "
1129-
"information for EMUL or EEW.\n");
1163+
if (ConsumerInfo.isUnknown() || ProducerInfo.isUnknown()) {
1164+
LLVM_DEBUG(dbgs() << " Abort due to unknown operand information.\n");
11301165
LLVM_DEBUG(dbgs() << " ConsumerInfo is: " << ConsumerInfo << "\n");
11311166
LLVM_DEBUG(dbgs() << " ProducerInfo is: " << ProducerInfo << "\n");
1132-
CanReduceVL = false;
1133-
break;
1167+
return std::nullopt;
1168+
}
1169+
1170+
// If the operand is used as a scalar operand, then the EEW must be
1171+
// compatible. Otherwise, the EMUL *and* EEW must be compatible.
1172+
bool IsVectorOpUsedAsScalarOp = isVectorOpUsedAsScalarOp(UserOp);
1173+
if ((IsVectorOpUsedAsScalarOp &&
1174+
!OperandInfo::EEWAreEqual(ConsumerInfo, ProducerInfo)) ||
1175+
(!IsVectorOpUsedAsScalarOp &&
1176+
!OperandInfo::EMULAndEEWAreEqual(ConsumerInfo, ProducerInfo))) {
1177+
LLVM_DEBUG(
1178+
dbgs()
1179+
<< " Abort due to incompatible information for EMUL or EEW.\n");
1180+
LLVM_DEBUG(dbgs() << " ConsumerInfo is: " << ConsumerInfo << "\n");
1181+
LLVM_DEBUG(dbgs() << " ProducerInfo is: " << ProducerInfo << "\n");
1182+
return std::nullopt;
11341183
}
11351184
}
1136-
return CanReduceVL;
1185+
1186+
return CommonVL;
11371187
}
11381188

11391189
bool RISCVVLOptimizer::tryReduceVL(MachineInstr &OrigMI) {
@@ -1145,12 +1195,11 @@ bool RISCVVLOptimizer::tryReduceVL(MachineInstr &OrigMI) {
11451195
MachineInstr &MI = *Worklist.pop_back_val();
11461196
LLVM_DEBUG(dbgs() << "Trying to reduce VL for " << MI << "\n");
11471197

1148-
const MachineOperand *CommonVL = nullptr;
1149-
bool CanReduceVL = true;
1150-
if (isVectorRegClass(MI.getOperand(0).getReg(), MRI))
1151-
CanReduceVL = checkUsers(CommonVL, MI);
1198+
if (!isVectorRegClass(MI.getOperand(0).getReg(), MRI))
1199+
continue;
11521200

1153-
if (!CanReduceVL || !CommonVL)
1201+
auto CommonVL = checkUsers(MI);
1202+
if (!CommonVL)
11541203
continue;
11551204

11561205
assert((CommonVL->isImm() || CommonVL->getReg().isVirtual()) &&

llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-formation.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ define i32 @reduce_and_16xi32_prefix5(ptr %p) {
530530
; CHECK: # %bb.0:
531531
; CHECK-NEXT: vsetivli zero, 5, e32, m2, ta, ma
532532
; CHECK-NEXT: vle32.v v8, (a0)
533-
; CHECK-NEXT: vsetivli zero, 5, e32, m1, ta, ma
533+
; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma
534534
; CHECK-NEXT: vmv.v.i v10, -1
535535
; CHECK-NEXT: vsetivli zero, 5, e32, m2, ta, ma
536536
; CHECK-NEXT: vredand.vs v8, v8, v10
@@ -725,7 +725,7 @@ define i32 @reduce_umin_16xi32_prefix5(ptr %p) {
725725
; RV32: # %bb.0:
726726
; RV32-NEXT: vsetivli zero, 5, e32, m2, ta, ma
727727
; RV32-NEXT: vle32.v v8, (a0)
728-
; RV32-NEXT: vsetivli zero, 5, e32, m1, ta, ma
728+
; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma
729729
; RV32-NEXT: vmv.v.i v10, -1
730730
; RV32-NEXT: vsetivli zero, 5, e32, m2, ta, ma
731731
; RV32-NEXT: vredminu.vs v8, v8, v10

llvm/test/CodeGen/RISCV/rvv/fold-binary-reduce.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ entry:
1818
define i64 @reduce_add2(<4 x i64> %v) {
1919
; CHECK-LABEL: reduce_add2:
2020
; CHECK: # %bb.0: # %entry
21-
; CHECK-NEXT: vsetivli zero, 4, e64, m1, ta, ma
21+
; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma
2222
; CHECK-NEXT: vmv.v.i v10, 8
2323
; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma
2424
; CHECK-NEXT: vredsum.vs v8, v8, v10

llvm/test/CodeGen/RISCV/rvv/vl-opt-op-info.mir

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,3 +1174,116 @@ body: |
11741174
%x:vr = PseudoVMAND_MM_B1 $noreg, $noreg, -1, 0
11751175
%y:vr = PseudoVIOTA_M_MF2 $noreg, %x, 1, 3 /* e8 */, 0
11761176
...
1177+
name: vred_vs2
1178+
body: |
1179+
bb.0:
1180+
; CHECK-LABEL: name: vred_vs2
1181+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1182+
; CHECK-NEXT: %y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1183+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1184+
%y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, $noreg, 1, 3 /* e8 */, 0
1185+
...
1186+
---
1187+
name: vred_vs1
1188+
body: |
1189+
bb.0:
1190+
; CHECK-LABEL: name: vred_vs1
1191+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1192+
; CHECK-NEXT: %y:vr = PseudoVREDAND_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0 /* tu, mu */
1193+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1194+
%y:vr = PseudoVREDAND_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0
1195+
...
1196+
---
1197+
name: vred_vs1_vs2
1198+
body: |
1199+
bb.0:
1200+
; CHECK-LABEL: name: vred_vs1_vs2
1201+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1202+
; CHECK-NEXT: %y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, %x, 1, 3 /* e8 */, 0 /* tu, mu */
1203+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1204+
%y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, %x, 1, 3 /* e8 */, 0
1205+
...
1206+
---
1207+
name: vred_vs1_vs2_incompatible_eew
1208+
body: |
1209+
bb.0:
1210+
; CHECK-LABEL: name: vred_vs1_vs2_incompatible_eew
1211+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0 /* tu, mu */
1212+
; CHECK-NEXT: %y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, %x, 1, 4 /* e16 */, 0 /* tu, mu */
1213+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1214+
%y:vr = PseudoVREDAND_VS_M1_E8 $noreg, %x, %x, 1, 4 /* e16 */, 0
1215+
...
1216+
---
1217+
name: vred_vs1_vs2_incompatible_emul
1218+
body: |
1219+
bb.0:
1220+
; CHECK-LABEL: name: vred_vs1_vs2_incompatible_emul
1221+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0 /* tu, mu */
1222+
; CHECK-NEXT: %y:vr = PseudoVREDAND_VS_MF2_E8 $noreg, %x, %x, 1, 3 /* e8 */, 0 /* tu, mu */
1223+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1224+
%y:vr = PseudoVREDAND_VS_MF2_E8 $noreg, %x, %x, 1, 3 /* e8 */, 0
1225+
...
1226+
---
1227+
name: vred_other_user_is_vl0
1228+
body: |
1229+
bb.0:
1230+
; CHECK-LABEL: name: vred_other_user_is_vl0
1231+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1232+
; CHECK-NEXT: %y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0 /* tu, mu */
1233+
; CHECK-NEXT: %z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0 /* tu, mu */
1234+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1235+
%y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0
1236+
%z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0
1237+
...
1238+
---
1239+
name: vred_both_vl0
1240+
body: |
1241+
bb.0:
1242+
; CHECK-LABEL: name: vred_both_vl0
1243+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1244+
; CHECK-NEXT: %y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 0, 3 /* e8 */, 0 /* tu, mu */
1245+
; CHECK-NEXT: %z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0 /* tu, mu */
1246+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1247+
%y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 0, 3 /* e8 */, 0
1248+
%z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0
1249+
...
1250+
---
1251+
name: vred_vl0_and_vlreg
1252+
body: |
1253+
bb.0:
1254+
; CHECK-LABEL: name: vred_vl0_and_vlreg
1255+
; CHECK: %vl:gprnox0 = COPY $x1
1256+
; CHECK-NEXT: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 1, 3 /* e8 */, 0 /* tu, mu */
1257+
; CHECK-NEXT: %y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, %vl, 3 /* e8 */, 0 /* tu, mu */
1258+
; CHECK-NEXT: %z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0 /* tu, mu */
1259+
%vl:gprnox0 = COPY $x1
1260+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1261+
%y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, %vl, 3 /* e8 */, 0
1262+
%z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 0, 3 /* e8 */, 0
1263+
...
1264+
---
1265+
name: vred_vlreg_and_vl0
1266+
body: |
1267+
bb.0:
1268+
; CHECK-LABEL: name: vred_vlreg_and_vl0
1269+
; CHECK: %vl:gprnox0 = COPY $x1
1270+
; CHECK-NEXT: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0 /* tu, mu */
1271+
; CHECK-NEXT: %y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 0, 3 /* e8 */, 0 /* tu, mu */
1272+
; CHECK-NEXT: %z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, %vl, 3 /* e8 */, 0 /* tu, mu */
1273+
%vl:gprnox0 = COPY $x1
1274+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1275+
%y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 0, 3 /* e8 */, 0
1276+
%z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, %vl, 3 /* e8 */, 0
1277+
...
1278+
---
1279+
name: vred_other_user_is_vl2
1280+
body: |
1281+
bb.0:
1282+
; CHECK-LABEL: name: vred_other_user_is_vl2
1283+
; CHECK: %x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, 2, 3 /* e8 */, 0 /* tu, mu */
1284+
; CHECK-NEXT: %y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0 /* tu, mu */
1285+
; CHECK-NEXT: %z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 2, 3 /* e8 */, 0 /* tu, mu */
1286+
%x:vr = PseudoVADD_VV_M1 $noreg, $noreg, $noreg, -1, 3 /* e8 */, 0
1287+
%y:vr = PseudoVREDSUM_VS_M1_E8 $noreg, $noreg, %x, 1, 3 /* e8 */, 0
1288+
%z:vr = PseudoVADD_VV_M1 $noreg, %x, $noreg, 2, 3 /* e8 */, 0
1289+
...

0 commit comments

Comments
 (0)