@@ -1490,7 +1490,7 @@ void CombinerHelper::applyOptBrCondByInvertingCond(MachineInstr &MI,
1490
1490
Observer.changedInstr (*BrCond);
1491
1491
}
1492
1492
1493
-
1493
+
1494
1494
bool CombinerHelper::tryEmitMemcpyInline (MachineInstr &MI) {
1495
1495
MachineIRBuilder HelperBuilder (MI);
1496
1496
GISelObserverWrapper DummyObserver;
@@ -5286,6 +5286,141 @@ MachineInstr *CombinerHelper::buildSDivUsingMul(MachineInstr &MI) {
5286
5286
return MIB.buildMul (Ty, Res, Factor);
5287
5287
}
5288
5288
5289
+ bool CombinerHelper::matchSDivByPow2 (MachineInstr &MI) {
5290
+ assert (MI.getOpcode () == TargetOpcode::G_SDIV && " Expected SDIV" );
5291
+ if (MI.getFlag (MachineInstr::MIFlag::IsExact))
5292
+ return false ;
5293
+ auto &SDiv = cast<GenericMachineInstr>(MI);
5294
+ Register RHS = SDiv.getReg (2 );
5295
+ auto MatchPow2 = [&](const Constant *C) {
5296
+ if (auto *CI = dyn_cast<ConstantInt>(C))
5297
+ return CI->getValue ().isPowerOf2 () || CI->getValue ().isNegatedPowerOf2 ();
5298
+ return false ;
5299
+ };
5300
+ return matchUnaryPredicate (MRI, RHS, MatchPow2, /* AllowUndefs= */ false );
5301
+ }
5302
+
5303
+ void CombinerHelper::applySDivByPow2 (MachineInstr &MI) {
5304
+ assert (MI.getOpcode () == TargetOpcode::G_SDIV && " Expected SDIV" );
5305
+ auto &SDiv = cast<GenericMachineInstr>(MI);
5306
+ Register Dst = SDiv.getReg (0 );
5307
+ Register LHS = SDiv.getReg (1 );
5308
+ Register RHS = SDiv.getReg (2 );
5309
+ LLT Ty = MRI.getType (Dst);
5310
+ LLT ShiftAmtTy = getTargetLowering ().getPreferredShiftAmountTy (Ty);
5311
+
5312
+ Builder.setInstrAndDebugLoc (MI);
5313
+
5314
+ unsigned Bitwidth = Ty.getScalarSizeInBits ();
5315
+ auto Zero = Builder.buildConstant (Ty, 0 );
5316
+
5317
+ auto RHSC = getConstantOrConstantSplatVector (RHS);
5318
+ if (RHSC.has_value ()) {
5319
+ auto RHSCV = *RHSC;
5320
+
5321
+ // Special case: (sdiv X, 1) -> X
5322
+ if (RHSCV.isOne ()) {
5323
+ replaceSingleDefInstWithReg (MI, LHS);
5324
+ return ;
5325
+ }
5326
+ // Special Case: (sdiv X, -1) -> 0-X
5327
+ if (RHSCV.isAllOnes ()) {
5328
+ auto Sub = Builder.buildSub (Ty, Zero, LHS);
5329
+ replaceSingleDefInstWithReg (MI, Sub->getOperand (0 ).getReg ());
5330
+ return ;
5331
+ }
5332
+
5333
+
5334
+ unsigned TrailingZeros = RHSCV.countTrailingZeros ();
5335
+ auto C1 = Builder.buildConstant (ShiftAmtTy, TrailingZeros);
5336
+ auto Inexact = Builder.buildConstant (ShiftAmtTy, Bitwidth - TrailingZeros);
5337
+ auto Sign = Builder.buildAShr (
5338
+ Ty, LHS, Builder.buildConstant (ShiftAmtTy, Bitwidth - 1 ));
5339
+ // Add (LHS < 0) ? abs2 - 1 : 0;
5340
+ auto Srl = Builder.buildShl (Ty, Sign, Inexact);
5341
+ auto Add = Builder.buildAdd (Ty, LHS, Srl);
5342
+ auto Sra = Builder.buildAShr (Ty, Add, C1);
5343
+
5344
+ // If dividing by a positive value, we're done. Otherwise, the result must
5345
+ // be negated.
5346
+ auto Res = RHSCV.isNegative () ? Builder.buildSub (Ty, Zero, Sra) : Sra;
5347
+ replaceSingleDefInstWithReg (MI, Res->getOperand (0 ).getReg ());
5348
+ return ;
5349
+ }
5350
+
5351
+ // RHS is not a splat vector. Build the above version with instructions.
5352
+ auto Bits = Builder.buildConstant (ShiftAmtTy, Bitwidth);
5353
+ auto C1 = Builder.buildCTTZ (Ty, RHS);
5354
+ C1 = Builder.buildZExtOrTrunc (ShiftAmtTy, C1);
5355
+ auto Inexact = Builder.buildSub (ShiftAmtTy, Bits, C1);
5356
+ auto Sign = Builder.buildAShr (
5357
+ Ty, LHS, Builder.buildConstant (ShiftAmtTy, Bitwidth - 1 ));
5358
+
5359
+ // Add (LHS < 0) ? abs2 - 1 : 0;
5360
+ auto Srl = Builder.buildShl (Ty, Sign, Inexact);
5361
+ auto Add = Builder.buildAdd (Ty, LHS, Srl);
5362
+ auto Sra = Builder.buildAShr (Ty, Add, C1);
5363
+
5364
+ LLT CCVT = LLT::vector (Ty.getElementCount (), 1 );
5365
+
5366
+ auto One = Builder.buildConstant (Ty, 1 );
5367
+ auto AllOnes =
5368
+ Builder.buildConstant (Ty, APInt::getAllOnes (Ty.getScalarSizeInBits ()));
5369
+ auto IsOne = Builder.buildICmp (CmpInst::Predicate::ICMP_EQ, CCVT, RHS, One);
5370
+ auto IsAllOnes =
5371
+ Builder.buildICmp (CmpInst::Predicate::ICMP_EQ, CCVT, RHS, AllOnes);
5372
+ auto IsOneOrAllOnes = Builder.buildOr (CCVT, IsOne, IsAllOnes);
5373
+ Sra = Builder.buildSelect (Ty, IsOneOrAllOnes, LHS, Sra);
5374
+
5375
+ // If dividing by a positive value, we're done. Otherwise, the result must
5376
+ // be negated.
5377
+ auto Sub = Builder.buildSub (Ty, Zero, Sra);
5378
+ auto IsNeg = Builder.buildICmp (CmpInst::Predicate::ICMP_SLT, CCVT, LHS, Zero);
5379
+ auto Res = Builder.buildSelect (Ty, IsNeg, Sub, Sra);
5380
+ replaceSingleDefInstWithReg (MI, Res->getOperand (0 ).getReg ());
5381
+ }
5382
+
5383
+ bool CombinerHelper::matchUDivByPow2 (MachineInstr &MI) {
5384
+ assert (MI.getOpcode () == TargetOpcode::G_UDIV && " Expected UDIV" );
5385
+ if (MI.getFlag (MachineInstr::MIFlag::IsExact))
5386
+ return false ;
5387
+ auto &UDiv = cast<GenericMachineInstr>(MI);
5388
+ Register RHS = UDiv.getReg (2 );
5389
+ auto MatchPow2 = [&](const Constant *C) {
5390
+ if (auto *CI = dyn_cast<ConstantInt>(C))
5391
+ return CI->getValue ().isPowerOf2 ();
5392
+ return false ;
5393
+ };
5394
+ return matchUnaryPredicate (MRI, RHS, MatchPow2, /* AllowUndefs= */ false );
5395
+ }
5396
+
5397
+ void CombinerHelper::applyUDivByPow2 (MachineInstr &MI) {
5398
+ assert (MI.getOpcode () == TargetOpcode::G_UDIV && " Expected SDIV" );
5399
+ auto &UDiv = cast<GenericMachineInstr>(MI);
5400
+ Register Dst = UDiv.getReg (0 );
5401
+ Register LHS = UDiv.getReg (1 );
5402
+ Register RHS = UDiv.getReg (2 );
5403
+ LLT Ty = MRI.getType (Dst);
5404
+ LLT ShiftAmtTy = getTargetLowering ().getPreferredShiftAmountTy (Ty);
5405
+
5406
+ Builder.setInstrAndDebugLoc (MI);
5407
+
5408
+ auto RHSC = getIConstantVRegValWithLookThrough (RHS, MRI);
5409
+ assert (RHSC.has_value () && " RHS must be a constant" );
5410
+ auto RHSCV = RHSC->Value ;
5411
+
5412
+ // Special case: (udiv X, 1) -> X
5413
+ if (RHSCV.isOne ()) {
5414
+ replaceSingleDefInstWithReg (MI, LHS);
5415
+ return ;
5416
+ }
5417
+
5418
+ unsigned TrailingZeros = RHSCV.countTrailingZeros ();
5419
+ auto C1 = Builder.buildConstant (ShiftAmtTy, TrailingZeros);
5420
+ auto Res = Builder.buildLShr (Ty, LHS, C1);
5421
+ replaceSingleDefInstWithReg (MI, Res->getOperand (0 ).getReg ());
5422
+ }
5423
+
5289
5424
bool CombinerHelper::matchUMulHToLShr (MachineInstr &MI) {
5290
5425
assert (MI.getOpcode () == TargetOpcode::G_UMULH);
5291
5426
Register RHS = MI.getOperand (2 ).getReg ();
0 commit comments