}
}
-// Converts the given 32-bit operation to a target-specific SelectionDAG node.
-// Because i32 isn't a legal type for RV64, these operations would otherwise
-// be promoted to i64, making it difficult to select the SLLW/DIVUW/.../*W
-// later one because the fact the operation was originally of type i32 is
-// lost.
+// Converts the given i8/i16/i32 operation to a target-specific SelectionDAG
+// node. Because i8/i16/i32 isn't a legal type for RV64, these operations would
+// otherwise be promoted to i64, making it difficult to select the
+// SLLW/DIVUW/.../*W later one because the fact the operation was originally of
+// type i8/i16/i32 is lost.
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG,
- unsigned ExtOpc = ISD::ANY_EXTEND) {
+ unsigned ExtOpc0 = ISD::ANY_EXTEND,
+ unsigned ExtOpc1 = ISD::ANY_EXTEND) {
SDLoc DL(N);
RISCVISD::NodeType WOpcode = getRISCVWOpcode(N->getOpcode());
- SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));
- SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));
+ SDValue NewOp0 = DAG.getNode(ExtOpc0, DL, MVT::i64, N->getOperand(0));
+ SDValue NewOp1 = DAG.getNode(ExtOpc1, DL, MVT::i64, N->getOperand(1));
SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1);
// ReplaceNodeResults requires we maintain the same type for the return value.
return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
"Unexpected custom legalisation");
- if (N->getOperand(0).getOpcode() == ISD::Constant ||
- N->getOperand(1).getOpcode() == ISD::Constant)
+ // Don't promote division/remainder by constant since we should expand those
+ // to multiply by magic constant.
+ // FIXME: What if the expansion is disabled for minsize.
+ if (N->getOperand(1).getOpcode() == ISD::Constant)
return;
// If the input is i32, use ANY_EXTEND since the W instructions don't read
// the upper 32 bits. For other types we need to sign or zero extend
// based on the opcode.
- unsigned ExtOpc = ISD::ANY_EXTEND;
- if (VT != MVT::i32)
- ExtOpc = N->getOpcode() == ISD::SDIV ? ISD::SIGN_EXTEND
- : ISD::ZERO_EXTEND;
+ unsigned ExtOpc0 = ISD::ANY_EXTEND, ExtOpc1 = ISD::ANY_EXTEND;
+ if (VT != MVT::i32) {
+ ExtOpc0 = N->getOpcode() == ISD::SDIV ? ISD::SIGN_EXTEND
+ : ISD::ZERO_EXTEND;
+ ExtOpc1 = ExtOpc0;
+ } else if (N->getOperand(0).getOpcode() == ISD::Constant) {
+ // Sign extend i32 constants to improve materialization.
+ ExtOpc0 = ISD::SIGN_EXTEND;
+ }
- Results.push_back(customLegalizeToWOp(N, DAG, ExtOpc));
+ Results.push_back(customLegalizeToWOp(N, DAG, ExtOpc0, ExtOpc1));
break;
}
case ISD::UADDO:
;
; RV64IM-LABEL: udiv_constant_lhs:
; RV64IM: # %bb.0:
-; RV64IM-NEXT: slli a0, a0, 32
-; RV64IM-NEXT: srli a0, a0, 32
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: divu a0, a1, a0
+; RV64IM-NEXT: divuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = udiv i32 10, %a
ret i32 %1
; RV64IM: # %bb.0:
; RV64IM-NEXT: andi a0, a0, 255
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: divu a0, a1, a0
+; RV64IM-NEXT: divuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = udiv i8 10, %a
ret i8 %1
; RV64IM-NEXT: addiw a1, a1, -1
; RV64IM-NEXT: and a0, a0, a1
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: divu a0, a1, a0
+; RV64IM-NEXT: divuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = udiv i16 10, %a
ret i16 %1
;
; RV64IM-LABEL: sdiv_constant_lhs:
; RV64IM: # %bb.0:
-; RV64IM-NEXT: sext.w a0, a0
; RV64IM-NEXT: addi a1, zero, -10
-; RV64IM-NEXT: div a0, a1, a0
+; RV64IM-NEXT: divw a0, a1, a0
; RV64IM-NEXT: ret
%1 = sdiv i32 -10, %a
ret i32 %1
; RV64IM-NEXT: slli a0, a0, 56
; RV64IM-NEXT: srai a0, a0, 56
; RV64IM-NEXT: addi a1, zero, -10
-; RV64IM-NEXT: div a0, a1, a0
+; RV64IM-NEXT: divw a0, a1, a0
; RV64IM-NEXT: ret
%1 = sdiv i8 -10, %a
ret i8 %1
; RV64IM-NEXT: slli a0, a0, 48
; RV64IM-NEXT: srai a0, a0, 48
; RV64IM-NEXT: addi a1, zero, -10
-; RV64IM-NEXT: div a0, a1, a0
+; RV64IM-NEXT: divw a0, a1, a0
; RV64IM-NEXT: ret
%1 = sdiv i16 -10, %a
ret i16 %1
;
; RV64IM-LABEL: urem_constant_lhs:
; RV64IM: # %bb.0:
-; RV64IM-NEXT: slli a0, a0, 32
-; RV64IM-NEXT: srli a0, a0, 32
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: remu a0, a1, a0
+; RV64IM-NEXT: remuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = urem i32 10, %a
ret i32 %1
; RV64IM: # %bb.0:
; RV64IM-NEXT: andi a0, a0, 255
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: remu a0, a1, a0
+; RV64IM-NEXT: remuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = urem i8 10, %a
ret i8 %1
; RV64IM-NEXT: addiw a1, a1, -1
; RV64IM-NEXT: and a0, a0, a1
; RV64IM-NEXT: addi a1, zero, 10
-; RV64IM-NEXT: remu a0, a1, a0
+; RV64IM-NEXT: remuw a0, a1, a0
; RV64IM-NEXT: ret
%1 = urem i16 10, %a
ret i16 %1