LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 454 - InstCombine Transform Broken for set[lg]t (cast X to X++), CI
Summary: InstCombine Transform Broken for set[lg]t (cast X to X++), CI
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: trunk
Hardware: All All
: P normal
Assignee: Chris Lattner
URL:
Keywords: code-quality
Depends on:
Blocks:
 
Reported: 2004-11-02 09:04 PST by Reid Spencer
Modified: 2010-03-06 14:00 PST (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments
Assembly test case (115 bytes, text/plain)
2004-11-02 09:07 PST, Reid Spencer
Details
IRC Log Describing The Problem (1.60 KB, text/plain)
2004-11-02 09:14 PST, Reid Spencer
Details
Potential Patch (174.48 KB, patch)
2004-11-28 02:22 PST, Reid Spencer
Details
Test Case (3.65 KB, text/plain)
2004-11-28 02:25 PST, Reid Spencer
Details
Second Potential Patch (4.97 KB, patch)
2004-11-28 12:49 PST, Reid Spencer
Details
Third Potential Patch (6.89 KB, patch)
2004-11-28 13:56 PST, Reid Spencer
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Reid Spencer 2004-11-02 09:04:50 PST
Currently, the instruction combiner is broken when it tries to eliminate a setcc
with a cast and a constant as an argument under a number of constraints:

1. Only for setgt (>) and setlt (<)
2. Only when one of the operands is a case and the other is a constant
3. Only when the cast is to a larger integer type (e.g. sbyte -> int).

The code in question is the switch case starting at InstructionCombining.cpp:2021. 

Currently, the optimization has been disabled (leading to performance
degradation of generated code). The disablement was provided by this patch:

http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20041101/020140.html

This bug aims to fix the pessimization by correctly re-enabling the optimization.
Comment 1 Reid Spencer 2004-11-02 09:07:46 PST
Created attachment 182 [details]
Assembly test case

The obvious three line test case.
Comment 2 Reid Spencer 2004-11-02 09:14:47 PST
Created attachment 183 [details]
IRC Log Describing The Problem
Comment 3 Chris Lattner 2004-11-02 09:41:21 PST
This testcase may work better:

bool %nada(sbyte %X) {
  %Y = cast sbyte %X to uint
  %C = setgt uint %Y, 255
  ret bool %C
}

Otherwise, instcombine will just delete all of the code.  :)

In this case, it should be optimized to:

bool %nada(sbyte %X) {
  %C = setlt sbyte %X, 0
  ret bool %C
}

-Chris
Comment 4 Reid Spencer 2004-11-28 02:20:13 PST
Test Case Is Here:
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20041122/021393.html
Comment 5 Reid Spencer 2004-11-28 02:22:36 PST
Created attachment 185 [details]
Potential Patch

I've run through this numerous times and can't see anything wrong with it even
though it is substantially the same as the original.
Comment 6 Reid Spencer 2004-11-28 02:25:08 PST
Created attachment 186 [details]
Test Case

More rigorous test case
Comment 7 Reid Spencer 2004-11-28 02:27:46 PST
The "Potential Patch" produces the following xform from the "Test Case". I'd
appreciate it if you could review this and let me know if its okay to commit or
what I did wrong.

 
bool %lt_signed_to_large_unsigned(sbyte %SB) {
        ret bool true
} 
bool %lt_signed_to_large_signed(sbyte %SB) {
        ret bool true
}
bool %lt_signed_to_large_negative(sbyte %SB) {
        ret bool false
}
bool %lt_signed_to_small_unsigned(sbyte %SB) {
        %C = setlt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %lt_signed_to_small_signed(sbyte %SB) {
        %C = setlt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %lt_signed_to_small_negative(sbyte %SB) {
        %C = setlt sbyte %SB, -17               ; <bool> [#uses=1]
        ret bool %C
}
bool %lt_unsigned_to_large_unsigned(ubyte %SB) {
        ret bool true
}
bool %lt_unsigned_to_large_signed(ubyte %SB) {
        ret bool true
}
bool %lt_unsigned_to_large_negative(ubyte %SB) {
        ret bool false
}
bool %lt_unsigned_to_small_unsigned(ubyte %SB) {
        %C = setlt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %lt_unsigned_to_small_signed(ubyte %SB) {
        %C = setlt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %lt_unsigned_to_small_negative(ubyte %SB) {
        ret bool false
}
bool %gt_signed_to_large_unsigned(sbyte %SB) {
        %C = setgt sbyte %SB, -127              ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_signed_to_large_signed(sbyte %SB) {
        ret bool false
}
bool %gt_signed_to_large_negative(sbyte %SB) {
        ret bool true
}
bool %gt_signed_to_small_unsigned(sbyte %SB) {
        %C = setgt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_signed_to_small_signed(sbyte %SB) {
        %C = setgt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_signed_to_small_negative(sbyte %SB) {
        %C = setgt sbyte %SB, -17               ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_unsigned_to_large_unsigned(ubyte %SB) {
        ret bool false
}
bool %gt_unsigned_to_large_signed(ubyte %SB) {
        ret bool false
}
bool %gt_unsigned_to_large_negative(ubyte %SB) {
        ret bool true
}
bool %gt_unsigned_to_small_unsigned(ubyte %SB) {
        %C = setgt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_unsigned_to_small_signed(ubyte %SB) {
        %C = setgt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
bool %gt_unsigned_to_small_negative(ubyte %SB) {
        ret bool true
}
Comment 8 Reid Spencer 2004-11-28 12:49:11 PST
Created attachment 187 [details]
Second Potential Patch
Comment 9 Reid Spencer 2004-11-28 12:50:22 PST
Okay, the new patch now delivers:
 
bool %lt_signed_to_large_unsigned(sbyte %SB) {
        ret bool true
}
 
bool %lt_signed_to_large_signed(sbyte %SB) {
        ret bool true
}
 
bool %lt_signed_to_large_negative(sbyte %SB) {
        ret bool false
}
 
bool %lt_signed_to_small_unsigned(sbyte %SB) {
        %Y = cast sbyte %SB to ubyte            ; <ubyte> [#uses=1]
        %C = setlt ubyte %Y, 17         ; <bool> [#uses=1]
        ret bool %C
}
 
bool %lt_signed_to_small_signed(sbyte %SB) {
        %C = setlt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %lt_signed_to_small_negative(sbyte %SB) {
        %C = setlt sbyte %SB, -17               ; <bool> [#uses=1]
        ret bool %C
}
 
bool %lt_unsigned_to_large_unsigned(ubyte %SB) {
        ret bool true
}
 
bool %lt_unsigned_to_large_signed(ubyte %SB) {
        ret bool true
}
 
bool %lt_unsigned_to_large_negative(ubyte %SB) {
        ret bool false
}
 
bool %lt_unsigned_to_small_unsigned(ubyte %SB) {
        %C = setlt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %lt_unsigned_to_small_signed(ubyte %SB) {
        %C = setlt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %lt_unsigned_to_small_negative(ubyte %SB) {
        ret bool false
}
 
bool %gt_signed_to_large_unsigned(sbyte %SB) {
        %Y = cast sbyte %SB to ubyte            ; <ubyte> [#uses=1]
        %C = setgt ubyte %Y, 129                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_signed_to_large_signed(sbyte %SB) {
        ret bool false
}
 
bool %gt_signed_to_large_negative(sbyte %SB) {
        ret bool true
}
 
bool %gt_signed_to_small_unsigned(sbyte %SB) {
        %Y = cast sbyte %SB to ubyte            ; <ubyte> [#uses=1]
        %C = setgt ubyte %Y, 17         ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_signed_to_small_signed(sbyte %SB) {
        %C = setgt sbyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_signed_to_small_negative(sbyte %SB) {
        %C = setgt sbyte %SB, -17               ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_unsigned_to_large_unsigned(ubyte %SB) {
        ret bool false
}
 
bool %gt_unsigned_to_large_signed(ubyte %SB) {
        ret bool false
}
 
bool %gt_unsigned_to_large_negative(ubyte %SB) {
        ret bool true
}
 
bool %gt_unsigned_to_small_unsigned(ubyte %SB) {
        %C = setgt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_unsigned_to_small_signed(ubyte %SB) {
        %C = setgt ubyte %SB, 17                ; <bool> [#uses=1]
        ret bool %C
}
 
bool %gt_unsigned_to_small_negative(ubyte %SB) {
        ret bool true
}
Comment 10 Reid Spencer 2004-11-28 13:56:06 PST
Created attachment 188 [details]
Third Potential Patch

This is the same as the last one but it puts the guts of the Instruction::Cast
case of visitSetCondInst into visitSetCondInstWithCastAndConstant
Comment 11 Reid Spencer 2004-11-28 13:56:51 PST
The last patch is currently awaiting results of nightly testing. It will be
committed if it passes.
Comment 12 Reid Spencer 2004-11-28 15:32:34 PST
Resolution Patch Is Here:

http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20041122/021408.html
Comment 13 Chris Lattner 2005-01-16 21:21:27 PST
Part of this patch was disabled here:
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20050110/023419.html

It miscompiles the testcase in the commit.

-Chris
Comment 14 Chris Lattner 2005-04-24 02:00:37 PDT
This transform was reimplemented and reenabled here:
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20050418/025735.html

-Chris
Comment 15 Markus F.X.J. Oberhumer 2005-04-24 09:17:22 PDT
I just want to add a short note that the code contains several shifts in the
form  "(1ULL << C2->getType()->getPrimitiveSizeInBits())-1;" which _might_ cause
shift overflows.

Maybe it would be a good idea to implement some "uint64_t getHighBit(unsigned
bits)" and "uint64_t generateMask(unsigned bits)" helper functions that
correctly deal with bits == 64. Or these could also made member functions of Type.

Comment 16 Chris Lattner 2005-04-24 11:40:17 PDT
Excellent point, I'll audit these.

Thanks!

-Chris
Comment 17 Chris Lattner 2005-04-24 12:47:35 PDT
Yup, there were bugs.  Fixed here:
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20050418/025751.html

Thanks!

-Chris