Skip to content

Commit 3750558

Browse files
authored
[RISCV][GISel] Legalize G_SMULO/G_UMULO (#67635)
Update `LegalizerHelper::widenScalarMulo` to not create a mulo if we aren't going to use the overflow flag. This prevents needing to legalize the widened operation. This generates better code when we need to make a libcall for multiply.
1 parent 6e8013a commit 3750558

File tree

4 files changed

+831
-5
lines changed

4 files changed

+831
-5
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,8 +2141,20 @@ LegalizerHelper::widenScalarMulo(MachineInstr &MI, unsigned TypeIdx,
21412141
auto LeftOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {LHS});
21422142
auto RightOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {RHS});
21432143

2144-
auto Mulo = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy, OverflowTy},
2145-
{LeftOperand, RightOperand});
2144+
// Multiplication cannot overflow if the WideTy is >= 2 * original width,
2145+
// so we don't need to check the overflow result of larger type Mulo.
2146+
bool WideMulCanOverflow = WideTy.getScalarSizeInBits() < 2 * SrcBitWidth;
2147+
2148+
unsigned MulOpc =
2149+
WideMulCanOverflow ? MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2150+
2151+
MachineInstrBuilder Mulo;
2152+
if (WideMulCanOverflow)
2153+
Mulo = MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2154+
{LeftOperand, RightOperand});
2155+
else
2156+
Mulo = MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2157+
21462158
auto Mul = Mulo->getOperand(0);
21472159
MIRBuilder.buildTrunc(Result, Mul);
21482160

@@ -2160,9 +2172,7 @@ LegalizerHelper::widenScalarMulo(MachineInstr &MI, unsigned TypeIdx,
21602172
ExtResult = MIRBuilder.buildZExtInReg(WideTy, Mul, SrcBitWidth);
21612173
}
21622174

2163-
// Multiplication cannot overflow if the WideTy is >= 2 * original width,
2164-
// so we don't need to check the overflow result of larger type Mulo.
2165-
if (WideTy.getScalarSizeInBits() < 2 * SrcBitWidth) {
2175+
if (WideMulCanOverflow) {
21662176
auto Overflow =
21672177
MIRBuilder.buildICmp(CmpInst::ICMP_NE, OverflowTy, Mul, ExtResult);
21682178
// Finally check if the multiplication in the larger type itself overflowed.

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,31 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
145145
.legalFor({XLenLLT})
146146
.lower();
147147
// clang-format on
148+
149+
getActionDefinitionsBuilder({G_SMULO, G_UMULO})
150+
.minScalar(0, XLenLLT)
151+
.lower();
148152
} else {
149153
getActionDefinitionsBuilder(G_MUL)
150154
.libcallFor({XLenLLT, DoubleXLenLLT})
151155
.widenScalarToNextPow2(0)
152156
.clampScalar(0, XLenLLT, DoubleXLenLLT);
153157

154158
getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({XLenLLT});
159+
160+
getActionDefinitionsBuilder({G_SMULO, G_UMULO})
161+
.minScalar(0, XLenLLT)
162+
// Widen XLenLLT to DoubleXLenLLT so we can use a single libcall to get
163+
// the low bits for the mul result and high bits to do the overflow
164+
// check.
165+
.widenScalarIf(
166+
[=](const LegalityQuery &Query) {
167+
return Query.Types[0] == XLenLLT;
168+
},
169+
[=](const LegalityQuery &Query) {
170+
return std::make_pair(0, DoubleXLenLLT);
171+
})
172+
.lower();
155173
}
156174

157175
if (ST.hasStdExtM()) {

0 commit comments

Comments
 (0)