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 1499 - Instruction Combining misoptimization
Summary: Instruction Combining misoptimization
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: 2.0
Hardware: PC Linux
: P normal
Assignee: Lauro Venancio
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-06-05 16:25 PDT by Lauro Venancio
Modified: 2010-02-22 12:50 PST (History)
1 user (show)

See Also:
Fixed By Commit(s):


Attachments
bugpoint-tooptimize.bc (94.25 KB, application/octet-stream)
2007-06-05 16:26 PDT, Lauro Venancio
Details
fix (9.15 KB, patch)
2007-06-05 19:06 PDT, Lauro Venancio
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lauro Venancio 2007-06-05 16:25:08 PDT
Instruction Combining is wrongly optimizing the following code:

        %tmp30 = load i64* %tmp10               ; <i64> [#uses=1]
        %.cast = zext i32 63 to i64             ; <i64> [#uses=1]
        %tmp31 = ashr i64 %tmp30, %.cast                ; <i64> [#uses=1]
        %tmp3132 = trunc i64 %tmp31 to i32              ; <i32> [#uses=1]
        %tmp33 = or i32 %tmp3132, 1             ; <i32> [#uses=1]
        store i32 %tmp33, i32* %tmp9
        %tmp34 = load i32* %tmp9                ; <i32> [#uses=1]
        store i32 %tmp34, i32* %retval
        br label %return.exitStub

to 
        store i32 -1, i32* %tmp9
        store i32 -1, i32* %retval
        ret void
Comment 1 Lauro Venancio 2007-06-05 16:26:06 PDT
Created attachment 1001 [details]
bugpoint-tooptimize.bc
Comment 2 Lauro Venancio 2007-06-05 17:39:32 PDT
The problematic function (ffmpeg/libavutil/rational.h):

/**
 * Rational number num/den.
 */
typedef struct AVRational{
    int num; ///< numerator
    int den; ///< denominator
} AVRational;

/**
 * Compare two rationals.
 * @param a first rational
 * @param b second rational
 * @return 0 if a==b, 1 if a>b and -1 if a<b.
 */
static inline int av_cmp_q(AVRational a, AVRational b){
    const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;

    if(tmp) return (tmp>>63)|1;
    else    return 0;
}

--------------------------------------------------------------------------
I think the comment is wrong. This function returns 0 if a==b, 1 if a>b and
-0x7FFFFFFF if a<b.
Comment 3 Lauro Venancio 2007-06-05 19:06:30 PDT
Created attachment 1002 [details]
fix

Arithmetic left shift is not the inverse operation of arithmetic right shift.
The arithmetic left shift can result in overflow. So, we should preserve the
sign bit beyond making the arithmetic left shift.
Comment 4 Chris Lattner 2007-06-05 19:16:59 PDT
The patch is close, but not quite right.  The sign bit definitely does need to be demanded in some 
cases, but only in those cases where one of the shifted in bits is used.  For example, consider:

%Y = ashr i8 %X, 3

If we demand (f.e.) the low two bits from Y, then the input sign bit is not needed.  However, if any of 
the top three bits are demanded, then the input sign bit *is* demanded.

So basically, in that code, if any of the "high bits" are demanded, you should set the sign bit as 
demanded.  If none of the high bits are demanded, the sign bit should not be demanded.

Thanks again for investigating this Lauro!

-Chris