m_Not Pattern Question

I have a question about the pattern matching stuff that's used in the Instruction Combiner. If I have code like this:

     if (match(B, m_Select(m_Value(), m_ConstantInt(0), m_ConstantInt(-1)))) {
       if (match(C, m_Not(m_Value(B))))
         return SelectInst::Create(cast<User>(B)->getOperand(0), D, A);

and we match, the program fails during the "SelectInst::Create" phase. The problem is because B is now a Constant with "-2" as its value, so it has 0 operands. It appears that the m_Not() match is changing the value of B during this call.

Is this intentional? This happens in the "bind_ty" template in PatternMatch.h:

template<typename Class>
struct bind_ty {
   Class *&VR;
   bind_ty(Class *&V) : VR(V) {}

   template<typename ITy>
   bool match(ITy *V) {
     if (Class *CV = dyn_cast<Class>(V)) {
       VR = CV;
       return true;
     }
     return false;
   }
};

Why are we taking a reference to a pointer here? The assignment in the "match" method over writes the value of "B", which seems weird and wrong to me.

-bw

Bill Wendling wrote:

I have a question about the pattern matching stuff that's used in the Instruction Combiner. If I have code like this:

     if (match(B, m_Select(m_Value(), m_ConstantInt(0), m_ConstantInt(-1)))) {
       if (match(C, m_Not(m_Value(B))))
         return SelectInst::Create(cast<User>(B)->getOperand(0), D, A);

and we match, the program fails during the "SelectInst::Create" phase. The problem is because B is now a Constant with "-2" as its value, so it has 0 operands. It appears that the m_Not() match is changing the value of B during this call.

Is this intentional? This happens in the "bind_ty" template in PatternMatch.h:

template<typename Class>
struct bind_ty {
   Class *&VR;
   bind_ty(Class *&V) : VR(V) {}

   template<typename ITy>
   bool match(ITy *V) {
     if (Class *CV = dyn_cast<Class>(V)) {
       VR = CV;
       return true;
     }
     return false;
   }
};

Why are we taking a reference to a pointer here? The assignment in the "match" method over writes the value of "B", which seems weird and wrong to me.

This is deliberate. m_Foo(V) means "match any Foo and put its result into V." The way it's generally used is to declare empty variables, match against them, and test the equality:

   Value *A, *B, *C, *D;
   if (match(Expr, m_Or(m_And(A, B), m_And(C, D))) {
     if (B == D) {
       ... do optimization ...

Nick

Ah! Okay. Thanks for the explanation.

-bw