[llvm-commits] [llvm] r139263 - /llvm/trunk/lib/Target/README.txt

Duncan Sands baldrick at free.fr
Fri Sep 9 07:24:39 PDT 2011


Hi Benjamin,

>> I am trying to implement this as an exercise for me.
>> Attached you can find a patch which should implement the first
>> transformation as an InstructionSimplify optimization.
>>
>> Can you please give me feedback if I'm on the right track to do this
>> in InstSimplify and using the matcher?
>> My pattern looks complicated and very specific is there a easy/better
>> way to do it?
>
> These patterns are fine, but indeed very specific.

right - there are vast numbers of variations on this theme that occur in
practice.

  I think there is a
> more general way to do this. What I had in mind (maybe Duncan's idea
> is different and he knows InstSimplify a lot better than me), is to
> substitute the value from the equality comparison into the expression
> on the other side and see if it evaluates to true.
>
> (A == 0) | ((A&  ?) == 0) ->  (A == 0) | ((0&  ?) == 0) ->  (A == 0) | true
> Now we know that the first expression is redundant and we can drop it.
> We can use the same trick for&  with != and false.

My idea is along these lines but a bit more general.  First off, observe that
if X and Y are expressions and X => Y is true (X implies Y) then X & Y is
equivalent to X.  Similarly, if Y => X is true (Y implies X) than X | Y is
equivalent to X.

For example, if
   X := (A & ?) == 0
and
   Y := A == 0
then Y => X (if A is zero then certainly A & ? is zero).  Thus X | Y simplifies
to X which was the proposed transformation.

So to handle both & and | (and more besides) you need a way of determining when
ExpressionA => ExpressionB is true.  This can be done by assuming that
ExpressionA is true, and then simplifying ExpressionB using that.  If you can
simplify it to the constant "true" then you have shown that ExpressionA implies
ExpressionB.

In the above example, you would assume that "A == 0" is true (i.e. 0 can be
substituted for A), and then perform simplifications on "A & ? == 0" using
this fact.

How to do this in practice?  I'm imagining the following: define a "Facts"
class, into which you can push facts known to be true (push_true) and facts
know to be false (push_false), where a "fact" is an LLVM Value* with i1 type
(perhaps vector of i1 should be allowed too).  All the internal instsimplify
methods would get a Facts* argument, which can be null if there are no facts.

When trying to simplify a boolean X | Y, you would then do (schematically):

facts.push_true(Y);
Value *V = instsimplify(X, &facts);
facts.pop_back();
if (V && V->isAllOnesValue()) // X simplified to true when Y assumed true?
   // Yes!  X | Y simplifies to X.
   return X;
facts.push_true(X);
V = instsimplify(Y, &facts);
facts.pop_back();
if (V && V->isAllOnesValue()) // Y simplified to true when X assumed true?
   // Yes!  X | Y simplifies to Y.
   return Y;

Inside the various instsimplify routines, for example SimplifyICmpInst (which
is where you get when trying to simplify "A & ? == 0"), if the facts object is
not null, first the routine would try to simplify the arguments using the known
facts (i.e. it would call instsimplify with the expression "A & ?" and the
facts, and the expression "0" and the facts), and then continue with its usual
logic using the possibly simplified arguments.  So at the beginning of
SimplifyICmpInst,  SimplifyAndInst will be called with operands "A" and "?"
(and the facts).  It will try to simplify "A" in the presence of the fact
"A == 0", which will simplify A to 0 (here is where the facts are actually
used).  Maybe "?" will simplify or not, it doesn't matter.  Then the
SimplifyAndInst will continue its usual logic with the operands "0" and "?",
and return 0.  Then SimplifyICmpInst will continue with the operands "0" and
"0" and return "true".  And you're done.

Given the very limited amount of recursion that instsimplify does, the number
of facts would never exceed 2 or 3, so a very simple implementation would be
fine.  To get started, it would be enough to have it do something useful only
with equality facts like "A == 0 known true", but inequality facts turn up in
practice all the time so that can be added as an enhancement.

Well, maybe this is all too "heavy".  But that was what I had in mind.

>
> We have similar code in InstCombineSelect.cpp (look for
> SimplifyWithOpReplaced). To get this kind of cases it has to be
> enhanced to do the substitution on multiple levels though, I don't
> know how hard that is with the current InstSimplify machinery.

Pretty easy I think.

Ciao, Duncan.



More information about the llvm-commits mailing list