[LLVMbugs] [Bug 953] NEW: A bug + a fix in InstructionCombining

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Wed Oct 18 01:02:35 PDT 2006


           Summary: A bug + a fix in InstructionCombining
           Product: libraries
           Version: 1.8
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: minor
          Priority: P2
         Component: Scalar Optimizations
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: gil.dogon at mobileye.com

First I'd like to introduce myself.

I am an employee of MobileEye company, and we are using LLVM in order to compile
'C' code for a proprietary chip architceture. Generaly we are very happy with
LLVM  and we managed to have a little nice environment, including a debugger up
and running. During the developement ww stumbled upon the following bug:

we are using gccas explicitly and a short program to demonstarte the bug as
follows :

int t(int a,int b)
    return ((a&1) != 0)  != (b != 0);

runing gcc4.0 front end with no optimizations :

1360 tirana ~/VMPCompiler/VMP-gcc4> llvm-gcc --emit-llvm -S a.c -o a.s
1361 tirana ~/VMPCompiler/VMP-gcc4> cat a.s

; ModuleID = 'a.c'
target endian = little
target pointersize = 32
target triple = "i686-pc-linux-gnu"

implementation   ; Functions:

int %t(int %a, int %b) {
        %a_addr = alloca int            ; <int*> [#uses=2]
        %b_addr = alloca int            ; <int*> [#uses=2]
        %retval = alloca int, align 4           ; <int*> [#uses=2]
        %tmp = alloca int, align 4              ; <int*> [#uses=2]
        "alloca point" = cast int 0 to int              ; <int> [#uses=0]
        store int %a, int* %a_addr
        store int %b, int* %b_addr
        %tmp = load int* %a_addr                ; <int> [#uses=1]
        %tmp1 = and int %tmp, 1         ; <int> [#uses=1]
        %tmp1 = cast int %tmp1 to bool          ; <bool> [#uses=1]
        %tmp2 = load int* %b_addr               ; <int> [#uses=1]
        %tmp = setne int %tmp2, 0               ; <bool> [#uses=1]
        %tmp3 = xor bool %tmp1, %tmp            ; <bool> [#uses=1]
        %tmp3 = cast bool %tmp3 to int          ; <int> [#uses=1]
        store int %tmp3, int* %tmp
        %tmp4 = load int* %tmp          ; <int> [#uses=1]
        store int %tmp4, int* %retval
        br label %return

return:         ; preds = %entry
        %retval = load int* %retval             ; <int> [#uses=1]
        ret int %retval


declare int %printf(sbyte*, ...)

Gets us a correct program . However after optimizing it with gccas
the bug appears :

< 1386 tirana ~/VMPCompiler/VMP-gcc4> gccas a.s -o a.o
< 1389 tirana ~/VMPCompiler/VMP-gcc4> llvm-dis a.o -f -o a.ll
< 1390 tirana ~/VMPCompiler/VMP-gcc4> cat a.ll
; ModuleID = 'a.o'
target endian = little
target pointersize = 32
target triple = "i686-pc-linux-gnu"

implementation   ; Functions:

int %t(int %a, int %b) {
        %tmp1 = setne int %a, 0         ; <bool> [#uses=1]
        %tmp = setne int %b, 0          ; <bool> [#uses=1]
        %tmp3 = xor bool %tmp, %tmp1            ; <bool> [#uses=1]
        %tmp3 = cast bool %tmp3 to int          ; <int> [#uses=1]
        ret int %tmp3

As you can see this code is a bit too optimized and the and operation (a&1)
has been discarded.

I have chased down the bug and found the culprit is at the function 
SimplifyDemandedBits in InstructionCombining.cpp . In there the case of
cast from int to boolean is treated incorrectly as plain truncation.
where in fact a zero comparison is needed.

The following code snippet includes the bugfix:

 case Instruction::Cast: {
    const Type *SrcTy = I->getOperand(0)->getType();
    if (!SrcTy->isIntegral()) return false;

    //  GD : Bugfix: Cast from non-bool to bool require all the sources bits as
    //               it is not just a truncation ...
    //if (I->getType() == Type::BoolTy && SrcTy != Type::BoolTy) return false;

    // If this is an integer truncate or noop, just look in the input.

    if (SrcTy->getPrimitiveSizeInBits() >=
        I->getType()->getPrimitiveSizeInBits()) {
      if (SimplifyDemandedBits(I->getOperand(0), DemandedMask,
                               KnownZero, KnownOne, Depth+1))
        return true;
      assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");

I think this bug is rather rare because most of the time llvm does not generate
casts from int to boolean at the first place but have an expilit comparison.

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

More information about the llvm-bugs mailing list