From 4eebc8d003f25adf52a75702d6ee24f69330d920 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 8 May 2025 11:24:16 +0100 Subject: [PATCH] [PatternMatch] Mark various matchers const (NFC) (#138834) Mark matchers const and remove an extraneous template parameter in SCEVPatternMatch. Since SCEVPatternMatch is intertwined with PatternMatch, also fix constness issues there. --- .../Analysis/ScalarEvolutionPatternMatch.h | 20 +- llvm/include/llvm/IR/PatternMatch.h | 220 +++++++++--------- .../Transforms/Scalar/LoopIdiomRecognize.cpp | 2 +- llvm/unittests/IR/PatternMatch.cpp | 12 +- 4 files changed, 132 insertions(+), 122 deletions(-) diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h b/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h index 900f6d0fd05a..674147ca175e 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h +++ b/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h @@ -18,13 +18,12 @@ namespace llvm { namespace SCEVPatternMatch { -template -bool match(const SCEV *S, const Pattern &P) { +template bool match(const SCEV *S, const Pattern &P) { return P.match(S); } template struct cst_pred_ty : public Predicate { - bool match(const SCEV *S) { + bool match(const SCEV *S) const { assert((isa(S) || !S->getType()->isVectorTy()) && "no vector types expected from SCEVs"); auto *C = dyn_cast(S); @@ -33,20 +32,23 @@ template struct cst_pred_ty : public Predicate { }; struct is_zero { - bool isValue(const APInt &C) { return C.isZero(); } + bool isValue(const APInt &C) const { return C.isZero(); } }; + /// Match an integer 0. inline cst_pred_ty m_scev_Zero() { return cst_pred_ty(); } struct is_one { - bool isValue(const APInt &C) { return C.isOne(); } + bool isValue(const APInt &C) const { return C.isOne(); } }; + /// Match an integer 1. inline cst_pred_ty m_scev_One() { return cst_pred_ty(); } struct is_all_ones { - bool isValue(const APInt &C) { return C.isAllOnes(); } + bool isValue(const APInt &C) const { return C.isAllOnes(); } }; + /// Match an integer with all bits set. inline cst_pred_ty m_scev_AllOnes() { return cst_pred_ty(); @@ -85,7 +87,7 @@ struct specificscev_ty { specificscev_ty(const SCEV *Expr) : Expr(Expr) {} - template bool match(ITy *S) { return S == Expr; } + template bool match(ITy *S) const { return S == Expr; } }; /// Match if we have a specific specified SCEV. @@ -97,7 +99,7 @@ template struct SCEVUnaryExpr_match { SCEVUnaryExpr_match(Op0_t Op0) : Op0(Op0) {} - bool match(const SCEV *S) { + bool match(const SCEV *S) const { auto *E = dyn_cast(S); return E && E->getNumOperands() == 1 && Op0.match(E->getOperand(0)); } @@ -128,7 +130,7 @@ struct SCEVBinaryExpr_match { SCEVBinaryExpr_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {} - bool match(const SCEV *S) { + bool match(const SCEV *S) const { auto *E = dyn_cast(S); return E && E->getNumOperands() == 2 && Op0.match(E->getOperand(0)) && Op1.match(E->getOperand(1)); diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 46e0994cedc9..6242a686e7bc 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -47,11 +47,11 @@ namespace llvm { namespace PatternMatch { template bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); + return P.match(V); } template bool match(ArrayRef Mask, const Pattern &P) { - return const_cast(P).match(Mask); + return P.match(Mask); } template struct OneUse_match { @@ -59,7 +59,7 @@ template struct OneUse_match { OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { return V->hasOneUse() && SubPattern.match(V); } }; @@ -73,7 +73,7 @@ template struct AllowReassoc_match { AllowReassoc_match(const SubPattern_t &SP) : SubPattern(SP) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { auto *I = dyn_cast(V); return I && I->hasAllowReassoc() && SubPattern.match(I); } @@ -85,7 +85,7 @@ inline AllowReassoc_match m_AllowReassoc(const T &SubPattern) { } template struct class_match { - template bool match(ITy *V) { return isa(V); } + template bool match(ITy *V) const { return isa(V); } }; /// Match an arbitrary value and ignore it. @@ -143,7 +143,7 @@ struct undef_match { } return true; } - template bool match(ITy *V) { return check(V); } + template bool match(ITy *V) const { return check(V); } }; /// Match an arbitrary undef constant. This matches poison as well. @@ -175,7 +175,7 @@ inline class_match m_ConstantFP() { } struct constantexpr_match { - template bool match(ITy *V) { + template bool match(ITy *V) const { auto *C = dyn_cast(V); return C && (isa(C) || C->containsConstantExpression()); } @@ -196,7 +196,7 @@ template struct match_unless { match_unless(const Ty &Matcher) : M(Matcher) {} - template bool match(ITy *V) { return !M.match(V); } + template bool match(ITy *V) const { return !M.match(V); } }; /// Match if the inner matcher does *NOT* match. @@ -211,7 +211,7 @@ template struct match_combine_or { match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (L.match(V)) return true; if (R.match(V)) @@ -226,7 +226,7 @@ template struct match_combine_and { match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (L.match(V)) if (R.match(V)) return true; @@ -253,7 +253,7 @@ struct apint_match { apint_match(const APInt *&Res, bool AllowPoison) : Res(Res), AllowPoison(AllowPoison) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (auto *CI = dyn_cast(V)) { Res = &CI->getValue(); return true; @@ -278,7 +278,7 @@ struct apfloat_match { apfloat_match(const APFloat *&Res, bool AllowPoison) : Res(Res), AllowPoison(AllowPoison) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (auto *CI = dyn_cast(V)) { Res = &CI->getValueAPF(); return true; @@ -329,7 +329,7 @@ inline apfloat_match m_APFloatForbidPoison(const APFloat *&Res) { } template struct constantint_match { - template bool match(ITy *V) { + template bool match(ITy *V) const { if (const auto *CI = dyn_cast(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) @@ -355,7 +355,7 @@ template inline constantint_match m_ConstantInt() { template struct cstval_pred_ty : public Predicate { const Constant **Res = nullptr; - template bool match_impl(ITy *V) { + template bool match_impl(ITy *V) const { if (const auto *CV = dyn_cast(V)) return this->isValue(CV->getValue()); if (const auto *VTy = dyn_cast(V->getType())) { @@ -389,7 +389,7 @@ struct cstval_pred_ty : public Predicate { return false; } - template bool match(ITy *V) { + template bool match(ITy *V) const { if (this->match_impl(V)) { if (Res) *Res = cast(V); @@ -415,7 +415,7 @@ template struct api_pred_ty : public Predicate { api_pred_ty(const APInt *&R) : Res(R) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); @@ -442,7 +442,7 @@ template struct apf_pred_ty : public Predicate { apf_pred_ty(const APFloat *&R) : Res(R) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); @@ -472,7 +472,7 @@ template struct apf_pred_ty : public Predicate { template struct custom_checkfn { function_ref CheckFn; - bool isValue(const APTy &C) { return CheckFn(C); } + bool isValue(const APTy &C) const { return CheckFn(C); } }; /// Match an integer or vector where CheckFn(ele) for each element is true. @@ -500,7 +500,7 @@ m_CheckedFp(const Constant *&V, function_ref CheckFn) { } struct is_any_apint { - bool isValue(const APInt &C) { return true; } + bool isValue(const APInt &C) const { return true; } }; /// Match an integer or vector with any integral constant. /// For vectors, this includes constants with undefined elements. @@ -509,7 +509,7 @@ inline cst_pred_ty m_AnyIntegralConstant() { } struct is_shifted_mask { - bool isValue(const APInt &C) { return C.isShiftedMask(); } + bool isValue(const APInt &C) const { return C.isShiftedMask(); } }; inline cst_pred_ty m_ShiftedMask() { @@ -517,7 +517,7 @@ inline cst_pred_ty m_ShiftedMask() { } struct is_all_ones { - bool isValue(const APInt &C) { return C.isAllOnes(); } + bool isValue(const APInt &C) const { return C.isAllOnes(); } }; /// Match an integer or vector with all bits set. /// For vectors, this includes constants with undefined elements. @@ -530,7 +530,7 @@ inline cst_pred_ty m_AllOnesForbidPoison() { } struct is_maxsignedvalue { - bool isValue(const APInt &C) { return C.isMaxSignedValue(); } + bool isValue(const APInt &C) const { return C.isMaxSignedValue(); } }; /// Match an integer or vector with values having all bits except for the high /// bit set (0x7f...). @@ -543,7 +543,7 @@ inline api_pred_ty m_MaxSignedValue(const APInt *&V) { } struct is_negative { - bool isValue(const APInt &C) { return C.isNegative(); } + bool isValue(const APInt &C) const { return C.isNegative(); } }; /// Match an integer or vector of negative values. /// For vectors, this includes constants with undefined elements. @@ -553,7 +553,7 @@ inline cst_pred_ty m_Negative() { inline api_pred_ty m_Negative(const APInt *&V) { return V; } struct is_nonnegative { - bool isValue(const APInt &C) { return C.isNonNegative(); } + bool isValue(const APInt &C) const { return C.isNonNegative(); } }; /// Match an integer or vector of non-negative values. /// For vectors, this includes constants with undefined elements. @@ -563,7 +563,7 @@ inline cst_pred_ty m_NonNegative() { inline api_pred_ty m_NonNegative(const APInt *&V) { return V; } struct is_strictlypositive { - bool isValue(const APInt &C) { return C.isStrictlyPositive(); } + bool isValue(const APInt &C) const { return C.isStrictlyPositive(); } }; /// Match an integer or vector of strictly positive values. /// For vectors, this includes constants with undefined elements. @@ -575,7 +575,7 @@ inline api_pred_ty m_StrictlyPositive(const APInt *&V) { } struct is_nonpositive { - bool isValue(const APInt &C) { return C.isNonPositive(); } + bool isValue(const APInt &C) const { return C.isNonPositive(); } }; /// Match an integer or vector of non-positive values. /// For vectors, this includes constants with undefined elements. @@ -585,14 +585,14 @@ inline cst_pred_ty m_NonPositive() { inline api_pred_ty m_NonPositive(const APInt *&V) { return V; } struct is_one { - bool isValue(const APInt &C) { return C.isOne(); } + bool isValue(const APInt &C) const { return C.isOne(); } }; /// Match an integer 1 or a vector with all elements equal to 1. /// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_One() { return cst_pred_ty(); } struct is_zero_int { - bool isValue(const APInt &C) { return C.isZero(); } + bool isValue(const APInt &C) const { return C.isZero(); } }; /// Match an integer 0 or a vector with all elements equal to 0. /// For vectors, this includes constants with undefined elements. @@ -601,7 +601,7 @@ inline cst_pred_ty m_ZeroInt() { } struct is_zero { - template bool match(ITy *V) { + template bool match(ITy *V) const { auto *C = dyn_cast(V); // FIXME: this should be able to do something for scalable vectors return C && (C->isNullValue() || cst_pred_ty().match(C)); @@ -612,7 +612,7 @@ struct is_zero { inline is_zero m_Zero() { return is_zero(); } struct is_power2 { - bool isValue(const APInt &C) { return C.isPowerOf2(); } + bool isValue(const APInt &C) const { return C.isPowerOf2(); } }; /// Match an integer or vector power-of-2. /// For vectors, this includes constants with undefined elements. @@ -620,7 +620,7 @@ inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } struct is_negated_power2 { - bool isValue(const APInt &C) { return C.isNegatedPowerOf2(); } + bool isValue(const APInt &C) const { return C.isNegatedPowerOf2(); } }; /// Match a integer or vector negated power-of-2. /// For vectors, this includes constants with undefined elements. @@ -632,7 +632,7 @@ inline api_pred_ty m_NegatedPower2(const APInt *&V) { } struct is_negated_power2_or_zero { - bool isValue(const APInt &C) { return !C || C.isNegatedPowerOf2(); } + bool isValue(const APInt &C) const { return !C || C.isNegatedPowerOf2(); } }; /// Match a integer or vector negated power-of-2. /// For vectors, this includes constants with undefined elements. @@ -645,7 +645,7 @@ m_NegatedPower2OrZero(const APInt *&V) { } struct is_power2_or_zero { - bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } + bool isValue(const APInt &C) const { return !C || C.isPowerOf2(); } }; /// Match an integer or vector of 0 or power-of-2 values. /// For vectors, this includes constants with undefined elements. @@ -657,7 +657,7 @@ inline api_pred_ty m_Power2OrZero(const APInt *&V) { } struct is_sign_mask { - bool isValue(const APInt &C) { return C.isSignMask(); } + bool isValue(const APInt &C) const { return C.isSignMask(); } }; /// Match an integer or vector with only the sign bit(s) set. /// For vectors, this includes constants with undefined elements. @@ -666,7 +666,7 @@ inline cst_pred_ty m_SignMask() { } struct is_lowbit_mask { - bool isValue(const APInt &C) { return C.isMask(); } + bool isValue(const APInt &C) const { return C.isMask(); } }; /// Match an integer or vector with only the low bit(s) set. /// For vectors, this includes constants with undefined elements. @@ -676,7 +676,7 @@ inline cst_pred_ty m_LowBitMask() { inline api_pred_ty m_LowBitMask(const APInt *&V) { return V; } struct is_lowbit_mask_or_zero { - bool isValue(const APInt &C) { return !C || C.isMask(); } + bool isValue(const APInt &C) const { return !C || C.isMask(); } }; /// Match an integer or vector with only the low bit(s) set. /// For vectors, this includes constants with undefined elements. @@ -690,7 +690,9 @@ inline api_pred_ty m_LowBitMaskOrZero(const APInt *&V) { struct icmp_pred_with_threshold { CmpPredicate Pred; const APInt *Thr; - bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); } + bool isValue(const APInt &C) const { + return ICmpInst::compare(C, *Thr, Pred); + } }; /// Match an integer or vector with every element comparing 'pred' (eg/ne/...) /// to Threshold. For vectors, this includes constants with undefined elements. @@ -703,14 +705,14 @@ m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) { } struct is_nan { - bool isValue(const APFloat &C) { return C.isNaN(); } + bool isValue(const APFloat &C) const { return C.isNaN(); } }; /// Match an arbitrary NaN constant. This includes quiet and signalling nans. /// For vectors, this includes constants with undefined elements. inline cstfp_pred_ty m_NaN() { return cstfp_pred_ty(); } struct is_nonnan { - bool isValue(const APFloat &C) { return !C.isNaN(); } + bool isValue(const APFloat &C) const { return !C.isNaN(); } }; /// Match a non-NaN FP constant. /// For vectors, this includes constants with undefined elements. @@ -719,14 +721,14 @@ inline cstfp_pred_ty m_NonNaN() { } struct is_inf { - bool isValue(const APFloat &C) { return C.isInfinity(); } + bool isValue(const APFloat &C) const { return C.isInfinity(); } }; /// Match a positive or negative infinity FP constant. /// For vectors, this includes constants with undefined elements. inline cstfp_pred_ty m_Inf() { return cstfp_pred_ty(); } struct is_noninf { - bool isValue(const APFloat &C) { return !C.isInfinity(); } + bool isValue(const APFloat &C) const { return !C.isInfinity(); } }; /// Match a non-infinity FP constant, i.e. finite or NaN. /// For vectors, this includes constants with undefined elements. @@ -735,7 +737,7 @@ inline cstfp_pred_ty m_NonInf() { } struct is_finite { - bool isValue(const APFloat &C) { return C.isFinite(); } + bool isValue(const APFloat &C) const { return C.isFinite(); } }; /// Match a finite FP constant, i.e. not infinity or NaN. /// For vectors, this includes constants with undefined elements. @@ -745,7 +747,7 @@ inline cstfp_pred_ty m_Finite() { inline apf_pred_ty m_Finite(const APFloat *&V) { return V; } struct is_finitenonzero { - bool isValue(const APFloat &C) { return C.isFiniteNonZero(); } + bool isValue(const APFloat &C) const { return C.isFiniteNonZero(); } }; /// Match a finite non-zero FP constant. /// For vectors, this includes constants with undefined elements. @@ -757,7 +759,7 @@ inline apf_pred_ty m_FiniteNonZero(const APFloat *&V) { } struct is_any_zero_fp { - bool isValue(const APFloat &C) { return C.isZero(); } + bool isValue(const APFloat &C) const { return C.isZero(); } }; /// Match a floating-point negative zero or positive zero. /// For vectors, this includes constants with undefined elements. @@ -766,7 +768,7 @@ inline cstfp_pred_ty m_AnyZeroFP() { } struct is_pos_zero_fp { - bool isValue(const APFloat &C) { return C.isPosZero(); } + bool isValue(const APFloat &C) const { return C.isPosZero(); } }; /// Match a floating-point positive zero. /// For vectors, this includes constants with undefined elements. @@ -775,7 +777,7 @@ inline cstfp_pred_ty m_PosZeroFP() { } struct is_neg_zero_fp { - bool isValue(const APFloat &C) { return C.isNegZero(); } + bool isValue(const APFloat &C) const { return C.isNegZero(); } }; /// Match a floating-point negative zero. /// For vectors, this includes constants with undefined elements. @@ -784,7 +786,7 @@ inline cstfp_pred_ty m_NegZeroFP() { } struct is_non_zero_fp { - bool isValue(const APFloat &C) { return C.isNonZero(); } + bool isValue(const APFloat &C) const { return C.isNonZero(); } }; /// Match a floating-point non-zero. /// For vectors, this includes constants with undefined elements. @@ -793,7 +795,9 @@ inline cstfp_pred_ty m_NonZeroFP() { } struct is_non_zero_not_denormal_fp { - bool isValue(const APFloat &C) { return !C.isDenormal() && C.isNonZero(); } + bool isValue(const APFloat &C) const { + return !C.isDenormal() && C.isNonZero(); + } }; /// Match a floating-point non-zero that is not a denormal. @@ -809,7 +813,7 @@ template struct bind_ty { bind_ty(Class *&V) : VR(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (auto *CV = dyn_cast(V)) { VR = CV; return true; @@ -880,7 +884,7 @@ struct immconstant_ty { }; struct match_immconstant_ty : immconstant_ty { - template bool match(ITy *V) { return isImmConstant(V); } + template bool match(ITy *V) const { return isImmConstant(V); } }; /// Match an arbitrary immediate Constant and ignore it. @@ -891,7 +895,7 @@ struct bind_immconstant_ty : immconstant_ty { bind_immconstant_ty(Constant *&V) : VR(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (isImmConstant(V)) { VR = cast(V); return true; @@ -911,7 +915,7 @@ struct specificval_ty { specificval_ty(const Value *V) : Val(V) {} - template bool match(ITy *V) { return V == Val; } + template bool match(ITy *V) const { return V == Val; } }; /// Match if we have a specific specified value. @@ -924,7 +928,7 @@ template struct deferredval_ty { deferredval_ty(Class *const &V) : Val(V) {} - template bool match(ITy *const V) { return V == Val; } + template bool match(ITy *const V) const { return V == Val; } }; /// Like m_Specific(), but works if the specific value to match is determined @@ -945,7 +949,7 @@ struct specific_fpval { specific_fpval(double V) : Val(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (const auto *CFP = dyn_cast(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) @@ -968,7 +972,7 @@ struct bind_const_intval_ty { bind_const_intval_ty(uint64_t &V) : VR(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { if (const auto *CV = dyn_cast(V)) if (CV->getValue().ule(UINT64_MAX)) { VR = CV->getZExtValue(); @@ -985,7 +989,7 @@ template struct specific_intval { specific_intval(const APInt &V) : Val(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { const auto *CI = dyn_cast(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) @@ -1000,7 +1004,7 @@ template struct specific_intval64 { specific_intval64(uint64_t V) : Val(V) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { const auto *CI = dyn_cast(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) @@ -1038,7 +1042,7 @@ struct specific_bbval { specific_bbval(BasicBlock *Val) : Val(Val) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { const auto *BB = dyn_cast(V); return BB && BB == Val; } @@ -1070,7 +1074,7 @@ struct AnyBinaryOp_match { // The LHS is always matched first. AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || (Commutable && L.match(I->getOperand(1)) && @@ -1093,7 +1097,7 @@ template struct AnyUnaryOp_match { AnyUnaryOp_match(const OP_t &X) : X(X) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return X.match(I->getOperand(0)); return false; @@ -1118,7 +1122,7 @@ struct BinaryOp_match { // The LHS is always matched first. BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template inline bool match(unsigned Opc, OpTy *V) { + template inline bool match(unsigned Opc, OpTy *V) const { if (V->getValueID() == Value::InstructionVal + Opc) { auto *I = cast(V); return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || @@ -1128,7 +1132,9 @@ struct BinaryOp_match { return false; } - template bool match(OpTy *V) { return match(Opcode, V); } + template bool match(OpTy *V) const { + return match(Opcode, V); + } }; template @@ -1159,7 +1165,7 @@ template struct FNeg_match { Op_t X; FNeg_match(const Op_t &Op) : X(Op) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { auto *FPMO = dyn_cast(V); if (!FPMO) return false; @@ -1290,7 +1296,7 @@ struct OverflowingBinaryOp_match { OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() != Opcode) return false; @@ -1392,7 +1398,7 @@ struct SpecificBinaryOp_match SpecificBinaryOp_match(unsigned Opcode, const LHS_t &LHS, const RHS_t &RHS) : BinaryOp_match(LHS, RHS), Opcode(Opcode) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { return BinaryOp_match::match(Opcode, V); } }; @@ -1411,7 +1417,7 @@ struct DisjointOr_match { DisjointOr_match(const LHS &L, const RHS &R) : L(L), R(R) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *PDI = dyn_cast(V)) { assert(PDI->getOpcode() == Instruction::Or && "Only or can be disjoint"); if (!PDI->isDisjoint()) @@ -1470,7 +1476,7 @@ struct XorLike_match { XorLike_match(const LHS &L, const RHS &R) : L(L), R(R) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() == Instruction::Sub && Op->hasNoUnsignedWrap() && PatternMatch::match(Op->getOperand(0), m_LowBitMask())) @@ -1502,7 +1508,7 @@ struct BinOpPred_match : Predicate { BinOpPred_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return this->isOpType(I->getOpcode()) && ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || @@ -1513,35 +1519,35 @@ struct BinOpPred_match : Predicate { }; struct is_shift_op { - bool isOpType(unsigned Opcode) { return Instruction::isShift(Opcode); } + bool isOpType(unsigned Opcode) const { return Instruction::isShift(Opcode); } }; struct is_right_shift_op { - bool isOpType(unsigned Opcode) { + bool isOpType(unsigned Opcode) const { return Opcode == Instruction::LShr || Opcode == Instruction::AShr; } }; struct is_logical_shift_op { - bool isOpType(unsigned Opcode) { + bool isOpType(unsigned Opcode) const { return Opcode == Instruction::LShr || Opcode == Instruction::Shl; } }; struct is_bitwiselogic_op { - bool isOpType(unsigned Opcode) { + bool isOpType(unsigned Opcode) const { return Instruction::isBitwiseLogicOp(Opcode); } }; struct is_idiv_op { - bool isOpType(unsigned Opcode) { + bool isOpType(unsigned Opcode) const { return Opcode == Instruction::SDiv || Opcode == Instruction::UDiv; } }; struct is_irem_op { - bool isOpType(unsigned Opcode) { + bool isOpType(unsigned Opcode) const { return Opcode == Instruction::SRem || Opcode == Instruction::URem; } }; @@ -1603,7 +1609,7 @@ template struct Exact_match { Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *PEO = dyn_cast(V)) return PEO->isExact() && SubPattern.match(V); return false; @@ -1632,7 +1638,7 @@ struct CmpClass_match { CmpClass_match(const LHS_t &LHS, const RHS_t &RHS) : Predicate(nullptr), L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) { if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { if (Predicate) @@ -1695,7 +1701,7 @@ struct SpecificCmpClass_match { SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) { if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) && L.match(I->getOperand(0)) && R.match(I->getOperand(1))) @@ -1746,7 +1752,7 @@ template struct OneOps_match { OneOps_match(const T0 &Op1) : Op1(Op1) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast(V); return Op1.match(I->getOperand(0)); @@ -1762,7 +1768,7 @@ template struct TwoOps_match { TwoOps_match(const T0 &Op1, const T1 &Op2) : Op1(Op1), Op2(Op2) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast(V); return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)); @@ -1782,7 +1788,7 @@ struct ThreeOps_match { ThreeOps_match(const T0 &Op1, const T1 &Op2, const T2 &Op3) : Op1(Op1), Op2(Op2), Op3(Op3) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast(V); if (!Op1.match(I->getOperand(0))) @@ -1807,16 +1813,18 @@ template struct AnyOps_match { // the last, for which the second version is called. The second version of // match_operands is also used to match each individual operand. template - std::enable_if_t match_operands(const Instruction *I) { + std::enable_if_t + match_operands(const Instruction *I) const { return match_operands(I) && match_operands(I); } template - std::enable_if_t match_operands(const Instruction *I) { + std::enable_if_t + match_operands(const Instruction *I) const { return std::get(Operands).match(I->getOperand(Idx)); } - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast(V); return I->getNumOperands() == sizeof...(OperandTypes) && @@ -1880,7 +1888,7 @@ template struct Shuffle_match { Shuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask) : Op1(Op1), Op2(Op2), Mask(Mask) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) { return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) && Mask.match(I->getShuffleMask()); @@ -1892,14 +1900,14 @@ template struct Shuffle_match { struct m_Mask { ArrayRef &MaskRef; m_Mask(ArrayRef &MaskRef) : MaskRef(MaskRef) {} - bool match(ArrayRef Mask) { + bool match(ArrayRef Mask) const { MaskRef = Mask; return true; } }; struct m_ZeroMask { - bool match(ArrayRef Mask) { + bool match(ArrayRef Mask) const { return all_of(Mask, [](int Elem) { return Elem == 0 || Elem == -1; }); } }; @@ -1907,13 +1915,13 @@ struct m_ZeroMask { struct m_SpecificMask { ArrayRef Val; m_SpecificMask(ArrayRef Val) : Val(Val) {} - bool match(ArrayRef Mask) { return Val == Mask; } + bool match(ArrayRef Mask) const { return Val == Mask; } }; struct m_SplatOrPoisonMask { int &SplatIndex; m_SplatOrPoisonMask(int &SplatIndex) : SplatIndex(SplatIndex) {} - bool match(ArrayRef Mask) { + bool match(ArrayRef Mask) const { const auto *First = find_if(Mask, [](int Elem) { return Elem != -1; }); if (First == Mask.end()) return false; @@ -1930,7 +1938,7 @@ template struct PtrAdd_match { PtrAdd_match(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp) : PointerOp(PointerOp), OffsetOp(OffsetOp) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { auto *GEP = dyn_cast(V); return GEP && GEP->getSourceElementType()->isIntegerTy(8) && PointerOp.match(GEP->getPointerOperand()) && @@ -1987,7 +1995,7 @@ template struct CastOperator_match { CastOperator_match(const Op_t &OpMatch) : Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *O = dyn_cast(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; @@ -1999,7 +2007,7 @@ template struct CastInst_match { CastInst_match(const Op_t &OpMatch) : Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return Op.match(I->getOperand(0)); return false; @@ -2013,7 +2021,7 @@ template struct PtrToIntSameSize_match { PtrToIntSameSize_match(const DataLayout &DL, const Op_t &OpMatch) : DL(DL), Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *O = dyn_cast(V)) return O->getOpcode() == Instruction::PtrToInt && DL.getTypeSizeInBits(O->getType()) == @@ -2028,7 +2036,7 @@ template struct NNegZExt_match { NNegZExt_match(const Op_t &OpMatch) : Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return I->hasNonNeg() && Op.match(I->getOperand(0)); return false; @@ -2040,7 +2048,7 @@ template struct NoWrapTrunc_match { NoWrapTrunc_match(const Op_t &OpMatch) : Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) return (I->getNoWrapKind() & WrapFlags) == WrapFlags && Op.match(I->getOperand(0)); @@ -2060,7 +2068,7 @@ template struct ElementWiseBitCast_match { ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { auto *I = dyn_cast(V); if (!I) return false; @@ -2219,7 +2227,7 @@ struct br_match { br_match(BasicBlock *&Succ) : Succ(Succ) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *BI = dyn_cast(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); @@ -2240,7 +2248,7 @@ struct brc_match { brc_match(const Cond_t &C, const TrueBlock_t &t, const FalseBlock_t &f) : Cond(C), T(t), F(f) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *BI = dyn_cast(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) return T.match(BI->getSuccessor(0)) && F.match(BI->getSuccessor(1)); @@ -2276,7 +2284,7 @@ struct MaxMin_match { // The LHS is always matched first. MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *II = dyn_cast(V)) { Intrinsic::ID IID = II->getIntrinsicID(); if ((IID == Intrinsic::smax && Pred_t::match(ICmpInst::ICMP_SGT)) || @@ -2522,7 +2530,7 @@ struct UAddWithOverflow_match { UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) : L(L), R(R), S(S) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { Value *ICmpLHS, *ICmpRHS; CmpPredicate Pred; if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) @@ -2588,7 +2596,7 @@ template struct Argument_match { Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { // FIXME: Should likely be switched to use `CallBase`. if (const auto *CI = dyn_cast(V)) return Val.match(CI->getArgOperand(OpI)); @@ -2608,7 +2616,7 @@ struct IntrinsicID_match { IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (const auto *CI = dyn_cast(V)) if (const auto *F = CI->getCalledFunction()) return F->getIntrinsicID() == ID; @@ -2949,7 +2957,7 @@ template struct Signum_match { Opnd_t Val; Signum_match(const Opnd_t &V) : Val(V) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { unsigned TypeSize = V->getType()->getScalarSizeInBits(); if (TypeSize == 0) return false; @@ -2989,7 +2997,7 @@ template struct ExtractValue_match { Opnd_t Val; ExtractValue_match(const Opnd_t &V) : Val(V) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) { // If Ind is -1, don't inspect indices if (Ind != -1 && @@ -3022,7 +3030,7 @@ template struct InsertValue_match { InsertValue_match(const T0 &Op0, const T1 &Op1) : Op0(Op0), Op1(Op1) {} - template bool match(OpTy *V) { + template bool match(OpTy *V) const { if (auto *I = dyn_cast(V)) { return Op0.match(I->getOperand(0)) && Op1.match(I->getOperand(1)) && I->getNumIndices() == 1 && Ind == I->getIndices()[0]; @@ -3043,7 +3051,7 @@ inline InsertValue_match m_InsertValue(const Val_t &Val, /// `ptrtoint(gep , * null, i32 1>` /// under the right conditions determined by DataLayout. struct VScaleVal_match { - template bool match(ITy *V) { + template bool match(ITy *V) const { if (m_Intrinsic().match(V)) return true; @@ -3086,7 +3094,7 @@ struct LogicalOp_match { LogicalOp_match(const LHS &L, const RHS &R) : L(L), R(R) {} - template bool match(T *V) { + template bool match(T *V) const { auto *I = dyn_cast(V); if (!I || !I->getType()->isIntOrIntVectorTy(1)) return false; diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 9c41c2798418..8f5d1ecba982 100644 --- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -2687,7 +2687,7 @@ template struct match_LoopInvariant { match_LoopInvariant(const SubPattern_t &SP, const Loop *L) : SubPattern(SP), L(L) {} - template bool match(ITy *V) { + template bool match(ITy *V) const { return L->isLoopInvariant(V) && SubPattern.match(V); } }; diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index e7600209e0b1..7b3a4ce36545 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -2038,27 +2038,27 @@ TEST_F(PatternMatchTest, IntrinsicMatcher) { namespace { struct is_unsigned_zero_pred { - bool isValue(const APInt &C) { return C.isZero(); } + bool isValue(const APInt &C) const { return C.isZero(); } }; struct is_float_zero_pred { - bool isValue(const APFloat &C) { return C.isZero(); } + bool isValue(const APFloat &C) const { return C.isZero(); } }; template struct always_true_pred { - bool isValue(const T &) { return true; } + bool isValue(const T &) const { return true; } }; template struct always_false_pred { - bool isValue(const T &) { return false; } + bool isValue(const T &) const { return false; } }; struct is_unsigned_max_pred { - bool isValue(const APInt &C) { return C.isMaxValue(); } + bool isValue(const APInt &C) const { return C.isMaxValue(); } }; struct is_float_nan_pred { - bool isValue(const APFloat &C) { return C.isNaN(); } + bool isValue(const APFloat &C) const { return C.isNaN(); } }; } // namespace