[llvm-commits] [PATCH] Fix: instcombine does not get max if hidden by sext

Frits van Bommel fvbommel at gmail.com
Fri Jan 7 08:01:03 PST 2011


On Fri, Jan 7, 2011 at 3:58 PM, Tobias Grosser
<grosser at fim.uni-passau.de> wrote:
> On 01/06/2011 05:49 AM, Frits van Bommel wrote:
>>
>> On Thu, Jan 6, 2011 at 7:49 AM, Chris Lattner<clattner at apple.com>  wrote:
>>>
>>> On Jan 3, 2011, at 8:52 PM, Tobias Grosser wrote:
>>>>
>>>> I fixed a recent bug report, that blocked me on a large FORTRAN test
>>>> case:
>>>>
>>>>    InstCombine:
>>>>    X = sext x ; x<  c ? X : C-1
>>>>    -->
>>>>    X = sext x; X>  C-1 ? C-1 : X
>>>>
>>>>    Instead of calculating this with mixed types promote all to the
>>>>    larger type. This enables scalar evolution to analyze this
>>>>    expression. PR8866
>>
>> Why only for sext and not zext? Does scalar evolution understand those
>> well enough that it's not needed there or was it just not useful for
>> your particular test case?
>> Or maybe the zext case is too different from the sext case to add easily?
>
> I wanted to check first if the approach I took was OK. The new version
> contains also zext support.


> Attached is the new version.

       switch (Pred) {
       default: break;
-      case ICmpInst::ICMP_ULT:
       case ICmpInst::ICMP_SLT: {
         // X < MIN ? T : F  -->  F
-        if (CI->isMinValue(Pred == ICmpInst::ICMP_SLT))
+        if (CI->isMinValue(true /* signed */))
           return ReplaceInstUsesWith(SI, FalseVal);
...
         break;
       }
-      case ICmpInst::ICMP_UGT:
       case ICmpInst::ICMP_SGT: {
         // X > MAX ? T : F  -->  F
-        if (CI->isMaxValue(Pred == ICmpInst::ICMP_SGT))
+        if (CI->isMaxValue(true /* signed */))
           return ReplaceInstUsesWith(SI, FalseVal);
+        break;
+      }

Why not do this for the unsigned cases anymore? X <u 0 is known false,
as is X >u -1.

Also, this switch might be cleaner as an if/else if but that's perhaps
a matter of taste.


+          // X = sext x; x >s c ? X : C+1 --> X = sext x; X <s C+1 ? C+1 : X
+          // X = sext x; x <s c ? X : C-1 --> X = sext x; X >s C-1 ? C-1 : X
+          if (Pred == ICI->getSignedPredicate()) {

You can use ICI->isSigned() or (I)CmpInst::isSigned(Pred) here.


I also noticed that you're no longer handling the sext + unsigned
compare case. I know it's kind of counter-intuitive, but when I was
examining the original patch I tried to find a case where it was wrong
but couldn't find one.
For instance, for x <u y:
If both x and y are <s 0 or both are >=s 0, (sext x) and (sext y) are
still the same relative values when interpreted as unsigned (just with
possibly some 1s prepended) so the result of x <u y doesn't change by
sext'ing the operands.
If x <s 0 and y >=s 0, x <u y is false and prepending 1s to x and 0s
to y doesn't change that.
If x >=s 0 and y <s 0, x <u y is true and prepending 0s to x and 1s to
y doesn't change that.
A similar argument can be made for x >u y.

The same doesn't hold for zext + signed compare, by the way. For
instance, 0xff <s 0x00, but 0x00ff >s 0x0000.




More information about the llvm-commits mailing list