@@ -2706,17 +2706,16 @@ Instruction *InstCombinerImpl::matchBSwapOrBitReverse(Instruction &I,
2706
2706
return LastInst;
2707
2707
}
2708
2708
2709
- // / Match UB-safe variants of the funnel shift intrinsic.
2710
- static Instruction *matchFunnelShift (Instruction &Or, InstCombinerImpl &IC,
2711
- const DominatorTree &DT) {
2709
+ std::optional<std::tuple<Intrinsic::ID, SmallVector<Value *, 3 >>>
2710
+ InstCombinerImpl::convertShlOrLShrToFShlOrFShr (Instruction &Or) {
2712
2711
// TODO: Can we reduce the code duplication between this and the related
2713
2712
// rotate matching code under visitSelect and visitTrunc?
2714
2713
unsigned Width = Or.getType ()->getScalarSizeInBits ();
2715
2714
2716
2715
Instruction *Or0, *Or1;
2717
2716
if (!match (Or.getOperand (0 ), m_Instruction (Or0)) ||
2718
2717
!match (Or.getOperand (1 ), m_Instruction (Or1)))
2719
- return nullptr ;
2718
+ return std::nullopt ;
2720
2719
2721
2720
bool IsFshl = true ; // Sub on LSHR.
2722
2721
SmallVector<Value *, 3 > FShiftArgs;
@@ -2730,7 +2729,7 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
2730
2729
!match (Or1,
2731
2730
m_OneUse (m_LogicalShift (m_Value (ShVal1), m_Value (ShAmt1)))) ||
2732
2731
Or0->getOpcode () == Or1->getOpcode ())
2733
- return nullptr ;
2732
+ return std::nullopt ;
2734
2733
2735
2734
// Canonicalize to or(shl(ShVal0, ShAmt0), lshr(ShVal1, ShAmt1)).
2736
2735
if (Or0->getOpcode () == BinaryOperator::LShr) {
@@ -2766,7 +2765,7 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
2766
2765
// might remove it after this fold). This still doesn't guarantee that the
2767
2766
// final codegen will match this original pattern.
2768
2767
if (match (R, m_OneUse (m_Sub (m_SpecificInt (Width), m_Specific (L))))) {
2769
- KnownBits KnownL = IC. computeKnownBits (L, /* Depth*/ 0 , &Or);
2768
+ KnownBits KnownL = computeKnownBits (L, /* Depth*/ 0 , &Or);
2770
2769
return KnownL.getMaxValue ().ult (Width) ? L : nullptr ;
2771
2770
}
2772
2771
@@ -2810,7 +2809,7 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
2810
2809
IsFshl = false ; // Sub on SHL.
2811
2810
}
2812
2811
if (!ShAmt)
2813
- return nullptr ;
2812
+ return std::nullopt ;
2814
2813
2815
2814
FShiftArgs = {ShVal0, ShVal1, ShAmt};
2816
2815
} else if (isa<ZExtInst>(Or0) || isa<ZExtInst>(Or1)) {
@@ -2832,18 +2831,18 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
2832
2831
const APInt *ZextHighShlAmt;
2833
2832
if (!match (Or0,
2834
2833
m_OneUse (m_Shl (m_Value (ZextHigh), m_APInt (ZextHighShlAmt)))))
2835
- return nullptr ;
2834
+ return std::nullopt ;
2836
2835
2837
2836
if (!match (Or1, m_ZExt (m_Value (Low))) ||
2838
2837
!match (ZextHigh, m_ZExt (m_Value (High))))
2839
- return nullptr ;
2838
+ return std::nullopt ;
2840
2839
2841
2840
unsigned HighSize = High->getType ()->getScalarSizeInBits ();
2842
2841
unsigned LowSize = Low->getType ()->getScalarSizeInBits ();
2843
2842
// Make sure High does not overlap with Low and most significant bits of
2844
2843
// High aren't shifted out.
2845
2844
if (ZextHighShlAmt->ult (LowSize) || ZextHighShlAmt->ugt (Width - HighSize))
2846
- return nullptr ;
2845
+ return std::nullopt ;
2847
2846
2848
2847
for (User *U : ZextHigh->users ()) {
2849
2848
Value *X, *Y;
@@ -2874,11 +2873,22 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
2874
2873
}
2875
2874
2876
2875
if (FShiftArgs.empty ())
2877
- return nullptr ;
2876
+ return std::nullopt ;
2878
2877
2879
2878
Intrinsic::ID IID = IsFshl ? Intrinsic::fshl : Intrinsic::fshr;
2880
- Function *F = Intrinsic::getDeclaration (Or.getModule (), IID, Or.getType ());
2881
- return CallInst::Create (F, FShiftArgs);
2879
+ return std::make_tuple (IID, FShiftArgs);
2880
+ }
2881
+
2882
+ // / Match UB-safe variants of the funnel shift intrinsic.
2883
+ static Instruction *matchFunnelShift (Instruction &Or, InstCombinerImpl &IC,
2884
+ const DominatorTree &DT) {
2885
+ if (auto Opt = IC.convertShlOrLShrToFShlOrFShr (Or)) {
2886
+ auto [IID, FShiftArgs] = *Opt;
2887
+ Function *F = Intrinsic::getDeclaration (Or.getModule (), IID, Or.getType ());
2888
+ return CallInst::Create (F, FShiftArgs);
2889
+ }
2890
+
2891
+ return nullptr ;
2882
2892
}
2883
2893
2884
2894
// / Attempt to combine or(zext(x),shl(zext(y),bw/2) concat packing patterns.
0 commit comments