return OrigOperand.getOpcode() == RISCVISD::VMV_V_X_VL;
}
- /// Get or create a value that can feed \p Root with the given \p ExtOpc.
- /// If \p ExtOpc is None, this returns the source of this operand.
+ /// Get or create a value that can feed \p Root with the given extension \p
+ /// SExt. If \p SExt is None, this returns the source of this operand.
/// \see ::getSource().
SDValue getOrCreateExtendedOp(const SDNode *Root, SelectionDAG &DAG,
- Optional<unsigned> ExtOpc) const {
+ Optional<bool> SExt) const {
+ if (!SExt.has_value())
+ return OrigOperand;
+
+ MVT NarrowVT = getNarrowType(Root);
+
SDValue Source = getSource();
- if (!ExtOpc)
+ if (Source.getValueType() == NarrowVT)
return Source;
- MVT NarrowVT = getNarrowType(Root);
+ unsigned ExtOpc = *SExt ? RISCVISD::VSEXT_VL : RISCVISD::VZEXT_VL;
+
// If we need an extension, we should be changing the type.
- assert(Source.getValueType() != NarrowVT && "Needless extension");
SDLoc DL(Root);
auto [Mask, VL] = getMaskAndVL(Root);
switch (OrigOperand.getOpcode()) {
case RISCVISD::VSEXT_VL:
case RISCVISD::VZEXT_VL:
- return DAG.getNode(*ExtOpc, DL, NarrowVT, Source, Mask, VL);
+ return DAG.getNode(ExtOpc, DL, NarrowVT, Source, Mask, VL);
case RISCVISD::VMV_V_X_VL:
return DAG.getNode(RISCVISD::VMV_V_X_VL, DL, NarrowVT,
DAG.getUNDEF(NarrowVT), Source.getOperand(1), VL);
struct CombineResult {
/// Opcode to be generated when materializing the combine.
unsigned TargetOpcode;
- /// Extension opcode to be applied to the source of LHS when materializing
- /// TargetOpcode.
- /// \see NodeExtensionHelper::getSource().
- Optional<unsigned> LHSExtOpc;
- /// Extension opcode to be applied to the source of RHS when materializing
- /// TargetOpcode.
- Optional<unsigned> RHSExtOpc;
+ // No value means no extension is needed. If extension is needed, the value
+ // indicates if it needs to be sign extended.
+ Optional<bool> SExtLHS;
+ Optional<bool> SExtRHS;
/// Root of the combine.
SDNode *Root;
/// LHS of the TargetOpcode.
CombineResult(unsigned TargetOpcode, SDNode *Root,
const NodeExtensionHelper &LHS, Optional<bool> SExtLHS,
const NodeExtensionHelper &RHS, Optional<bool> SExtRHS)
- : TargetOpcode(TargetOpcode), Root(Root), LHS(LHS), RHS(RHS) {
- MVT NarrowVT = NodeExtensionHelper::getNarrowType(Root);
- if (SExtLHS && LHS.getSource().getValueType() != NarrowVT)
- LHSExtOpc = *SExtLHS ? RISCVISD::VSEXT_VL : RISCVISD::VZEXT_VL;
- if (SExtRHS && RHS.getSource().getValueType() != NarrowVT)
- RHSExtOpc = *SExtRHS ? RISCVISD::VSEXT_VL : RISCVISD::VZEXT_VL;
- }
+ : TargetOpcode(TargetOpcode), SExtLHS(SExtLHS), SExtRHS(SExtRHS),
+ Root(Root), LHS(LHS), RHS(RHS) {}
/// Return a value that uses TargetOpcode and that can be used to replace
/// Root.
std::tie(Mask, VL) = NodeExtensionHelper::getMaskAndVL(Root);
Merge = Root->getOperand(2);
return DAG.getNode(TargetOpcode, SDLoc(Root), Root->getValueType(0),
- LHS.getOrCreateExtendedOp(Root, DAG, LHSExtOpc),
- RHS.getOrCreateExtendedOp(Root, DAG, RHSExtOpc), Merge,
+ LHS.getOrCreateExtendedOp(Root, DAG, SExtLHS),
+ RHS.getOrCreateExtendedOp(Root, DAG, SExtRHS), Merge,
Mask, VL);
}
};
%g = add <2 x i64> %e, %f
ret <2 x i64> %g
}
+
+define <4 x i64> @crash(<4 x i16> %x, <4 x i16> %y) {
+; CHECK-LABEL: crash:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma
+; CHECK-NEXT: vsext.vf4 v10, v8
+; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma
+; CHECK-NEXT: vzext.vf2 v8, v9
+; CHECK-NEXT: vwaddu.wv v10, v10, v8
+; CHECK-NEXT: vmv2r.v v8, v10
+; CHECK-NEXT: ret
+ %a = sext <4 x i16> %x to <4 x i64>
+ %b = zext <4 x i16> %y to <4 x i64>
+ %c = add <4 x i64> %a, %b
+ ret <4 x i64> %c
+}