@@ -846,9 +846,7 @@ namespace IGC
846
846
}
847
847
else if (I.getOpcode () == Instruction::Trunc)
848
848
{
849
- match =
850
- MatchRotate (I) ||
851
- MatchModifier (I);
849
+ match = MatchModifier (I);
852
850
}
853
851
else
854
852
{
@@ -1025,7 +1023,6 @@ namespace IGC
1025
1023
case Instruction::Or:
1026
1024
match =
1027
1025
MatchBoolOp (I) ||
1028
- MatchRotate (I) ||
1029
1026
MatchLogicAlu (I);
1030
1027
break ;
1031
1028
case Instruction::Xor:
@@ -3542,231 +3539,6 @@ namespace IGC
3542
3539
return found;
3543
3540
}
3544
3541
3545
- //
3546
- // Assume that V is of type T (integer) with N bits;
3547
- // and amt is of integer type too.
3548
- //
3549
- // rol (V, amt) = (V << amt) | ((unsigned(V) >> (N - amt))
3550
- // The function first finds the following generic pattern, note that
3551
- // [insts] denotes that "insts" are optional.
3552
- // [amt = and amt, N-1]
3553
- // high = shl V0, amt
3554
- // [amt0 = sub 0, amt || amt0 = sub N, amt]
3555
- // ; if amt is constant && amt + amt0 == N, this is unneeded
3556
- // [amt0 = and amt0, N-1]
3557
- // low = lshr V1, amt0
3558
- // R = or high, low
3559
- //
3560
- // case 0: [ likely, V is i32 or i64]
3561
- // V0 == V1 (V == V0 == V1)
3562
- //
3563
- // case 1: [ likely V is i16 or i8]
3564
- // V0 = sext V || zext V
3565
- // V1 = zext V
3566
- // Res = trunc R
3567
- //
3568
- // Res's type == V's type
3569
- //
3570
- // ror can be handled similarly. Note that
3571
- // ror (x, amt) = ((unsigned)x >> amt) | ( x << (N - amt))
3572
- // = rol (x, N - amt);
3573
- //
3574
- bool CodeGenPatternMatch::MatchRotate (llvm::Instruction& I)
3575
- {
3576
- using namespace llvm ::PatternMatch;
3577
-
3578
- struct RotatePattern : public Pattern
3579
- {
3580
- SSource sources[2 ];
3581
- e_opcode rotateOPCode;
3582
- llvm::Instruction* instruction;
3583
- virtual void Emit (EmitPass* pass, const DstModifier& modifier)
3584
- {
3585
- pass->Binary (rotateOPCode, sources, modifier);
3586
- }
3587
- };
3588
-
3589
- if (!m_Platform.supportRotateInstruction ())
3590
- {
3591
- return false ;
3592
- }
3593
-
3594
- // Sanity check:
3595
- // make sure that rotate is supported and "I" is a scalar "or" instruction
3596
- IGC_ASSERT_MESSAGE (false == I.getType ()->isVectorTy (), " Vector type not expected here" );
3597
-
3598
- uint64_t typeWidth = I.getType ()->getScalarSizeInBits ();
3599
- Instruction* OrInst = nullptr ;
3600
- if (I.getOpcode () == Instruction::Trunc)
3601
- {
3602
- if (BinaryOperator * tmp = dyn_cast<BinaryOperator>(I.getOperand (0 )))
3603
- {
3604
- if (tmp->getOpcode () != Instruction::Or)
3605
- {
3606
- return false ;
3607
- }
3608
- OrInst = tmp;
3609
- }
3610
- else
3611
- {
3612
- return false ;
3613
- }
3614
- }
3615
- else if (I.getOpcode () == Instruction::Or)
3616
- {
3617
- OrInst = cast<BinaryOperator>(&I);
3618
- }
3619
- else
3620
- {
3621
- IGC_ASSERT_MESSAGE (0 , " Should be invoked with Or/Trunc instruction" );
3622
- }
3623
-
3624
- // Do rotate only if
3625
- // 1) type is W/DW (HW only supports W/DW); and
3626
- // 2) both operands are instructions.
3627
- Instruction* LHS = dyn_cast<Instruction>(OrInst->getOperand (0 ));
3628
- Instruction* RHS = dyn_cast<Instruction>(OrInst->getOperand (1 ));
3629
- bool typeWidthSupported = typeWidth == 16 || typeWidth == 32 ;
3630
-
3631
- if (!LHS || !RHS || !typeWidthSupported)
3632
- {
3633
- return false ;
3634
- }
3635
-
3636
- // Make adjustment so that LHS is shl.
3637
- if (LHS->getOpcode () == Instruction::LShr)
3638
- {
3639
- Instruction* t = LHS;
3640
- LHS = RHS;
3641
- RHS = t;
3642
- }
3643
- if (LHS->getOpcode () != Instruction::Shl ||
3644
- RHS->getOpcode () != Instruction::LShr)
3645
- {
3646
- return false ;
3647
- }
3648
-
3649
- // first: find V
3650
- Value* V0 = LHS->getOperand (0 );
3651
- Value* V1 = RHS->getOperand (0 );
3652
- Value* V = nullptr ;
3653
- if (I.getOpcode () == Instruction::Or)
3654
- {
3655
- if (V0 == V1)
3656
- {
3657
- V = V0;
3658
- }
3659
- }
3660
- else
3661
- {
3662
- Value* X0, * X1;
3663
- if ((match (V0, m_ZExt (m_Value (X0))) || match (V0, m_SExt (m_Value (X0)))) &&
3664
- match (V1, m_ZExt (m_Value (X1))))
3665
- {
3666
- if (X0 == X1 && X0->getType ()->getScalarSizeInBits () == typeWidth)
3667
- {
3668
- V = X0;
3669
- }
3670
- }
3671
- }
3672
-
3673
- if (!V)
3674
- {
3675
- return false ;
3676
- }
3677
-
3678
- // Second: find amt
3679
- uint64_t typeMask = typeWidth - 1 ;
3680
- Value* LAmt = LHS->getOperand (1 );
3681
- Value* RAmt = RHS->getOperand (1 );
3682
- ConstantInt* C_LAmt = dyn_cast<ConstantInt>(LAmt);
3683
- ConstantInt* C_RAmt = dyn_cast<ConstantInt>(RAmt);
3684
- Value* X0, * X1;
3685
- Value* Amt = nullptr ;
3686
- bool isROL = true ;
3687
- if (C_LAmt || C_RAmt)
3688
- {
3689
- // If only one of shift-amounts is constant, it cannot be rotate.
3690
- if (C_LAmt && C_RAmt)
3691
- {
3692
- // For shift amount that is beyond the typewidth, the result is
3693
- // undefined. Here, we just use the LSB.
3694
- uint64_t c0 = C_LAmt->getZExtValue () & typeMask;
3695
- uint64_t c1 = C_RAmt->getZExtValue () & typeMask;
3696
- if ((c0 + c1) == typeWidth)
3697
- {
3698
- Amt = LAmt;
3699
- isROL = true ;
3700
- }
3701
- }
3702
- }
3703
- else
3704
- {
3705
- if (match (RAmt, m_And (m_Sub (m_Zero (), m_Value (X1)), m_SpecificInt (typeMask))) ||
3706
- match (RAmt, m_And (m_Sub (m_SpecificInt (typeWidth), m_Value (X1)), m_SpecificInt (typeMask))) ||
3707
- match (RAmt, m_Sub (m_Zero (), m_Value (X1))) ||
3708
- match (RAmt, m_Sub (m_SpecificInt (typeWidth), m_Value (X1))))
3709
- {
3710
- if (LAmt == X1 ||
3711
- (match (LAmt, m_And (m_Value (X0), m_SpecificInt (typeMask))) && (X1 == X0)))
3712
- {
3713
- Amt = X1;
3714
- isROL = true ;
3715
- }
3716
- }
3717
- if (!Amt &&
3718
- (match (LAmt, m_And (m_Sub (m_Zero (), m_Value (X1)), m_SpecificInt (typeMask))) ||
3719
- match (LAmt, m_And (m_Sub (m_SpecificInt (typeWidth), m_Value (X1)), m_SpecificInt (typeMask))) ||
3720
- match (LAmt, m_Sub (m_Zero (), m_Value (X1))) ||
3721
- match (LAmt, m_Sub (m_SpecificInt (typeWidth), m_Value (X1)))))
3722
- {
3723
- if (RAmt == X1 ||
3724
- (match (RAmt, m_And (m_Value (X0), m_SpecificInt (typeMask))) && (X1 == X0)))
3725
- {
3726
- Amt = X1;
3727
- isROL = false ;
3728
- }
3729
- }
3730
-
3731
- if (Amt)
3732
- {
3733
- Value* X0, * X1, * X2;
3734
- // 1) simple case: amt = 32 - X0; use amt1 as shift amount.
3735
- bool isReverse = match (Amt, m_Sub (m_SpecificInt (typeWidth), m_Value (X0)));
3736
-
3737
- // 2) t = 16 - X0 | t = 0 - X0 ; for example, t is i16/i8, etc
3738
- // t1 = t & 15
3739
- // amt = zext t1, i32
3740
- isReverse = isReverse ||
3741
- (match (Amt, m_ZExt (m_Value (X1))) &&
3742
- match (X1, m_And (m_Value (X2), m_SpecificInt (typeMask))) &&
3743
- (match (X2, m_Sub (m_SpecificInt (typeWidth), m_Value (X0))) ||
3744
- match (X2, m_Sub (m_Zero (), m_Value (X0)))));
3745
-
3746
- if (isReverse)
3747
- {
3748
- Amt = X0;
3749
- isROL = !isROL;
3750
- }
3751
- }
3752
- }
3753
-
3754
- if (!Amt)
3755
- {
3756
- return false ;
3757
- }
3758
-
3759
- // Found the pattern.
3760
- RotatePattern* pattern = new (m_allocator) RotatePattern ();
3761
- pattern->instruction = &I;
3762
- pattern->sources [0 ] = GetSource (V, true , false );
3763
- pattern->sources [1 ] = GetSource (Amt, true , false );
3764
- pattern->rotateOPCode = isROL ? EOPCODE_ROL : EOPCODE_ROR;
3765
-
3766
- AddPattern (pattern);
3767
- return true ;
3768
- }
3769
-
3770
3542
bool CodeGenPatternMatch::MatchFunnelShiftRotate (llvm::IntrinsicInst& I)
3771
3543
{
3772
3544
// Hanlde only funnel shift that can be turned into rotate.
0 commit comments