@@ -846,9 +846,7 @@ namespace IGC
846846 }
847847 else if (I.getOpcode () == Instruction::Trunc)
848848 {
849- match =
850- MatchRotate (I) ||
851- MatchModifier (I);
849+ match = MatchModifier (I);
852850 }
853851 else
854852 {
@@ -1025,7 +1023,6 @@ namespace IGC
10251023 case Instruction::Or:
10261024 match =
10271025 MatchBoolOp (I) ||
1028- MatchRotate (I) ||
10291026 MatchLogicAlu (I);
10301027 break ;
10311028 case Instruction::Xor:
@@ -3542,231 +3539,6 @@ namespace IGC
35423539 return found;
35433540 }
35443541
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-
37703542 bool CodeGenPatternMatch::MatchFunnelShiftRotate (llvm::IntrinsicInst& I)
37713543 {
37723544 // Hanlde only funnel shift that can be turned into rotate.
0 commit comments