[LLVMbugs] [Bug 3101] New: Instcombine promotes i32 mul to i64 mul

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Wed Nov 19 12:13:15 PST 2008


http://llvm.org/bugs/show_bug.cgi?id=3101

           Summary: Instcombine promotes i32 mul to i64 mul
           Product: libraries
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Scalar Optimizations
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: tilmann.scheller at googlemail.com
                CC: llvmbugs at cs.uiuc.edu


Translating the following snippet into LLVM IR on x86-64

long mul(long a, long b)
{
  return ((int) a) * ((int) b);
}

with llvm-gcc -O0 results in the following code:

; ModuleID = 'mul.bc'
target datalayout =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-unknown-linux-gnu"

define i64 @mul(i64 %a, i64 %b) nounwind {
entry:
        %a_addr = alloca i64            ; <i64*> [#uses=2]
        %b_addr = alloca i64            ; <i64*> [#uses=2]
        %retval = alloca i64            ; <i64*> [#uses=2]
        %0 = alloca i64         ; <i64*> [#uses=2]
        %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
        store i64 %a, i64* %a_addr
        store i64 %b, i64* %b_addr
        %1 = load i64* %a_addr, align 8         ; <i64> [#uses=1]
        %2 = trunc i64 %1 to i32                ; <i32> [#uses=1]
        %3 = load i64* %b_addr, align 8         ; <i64> [#uses=1]
        %4 = trunc i64 %3 to i32                ; <i32> [#uses=1]
        %5 = mul i32 %2, %4             ; <i32> [#uses=1]
        %6 = sext i32 %5 to i64         ; <i64> [#uses=1]
        store i64 %6, i64* %0, align 8
        %7 = load i64* %0, align 8              ; <i64> [#uses=1]
        store i64 %7, i64* %retval, align 8
        br label %return

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

Running opt -instcombine on this results in the following code:
; ModuleID = 'mulopt.bc'
target datalayout =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-unknown-linux-gnu"

define i64 @mul(i64 %a, i64 %b) nounwind {
entry:
        %retval = alloca i64            ; <i64*> [#uses=2]
        %0 = mul i64 %a, %b             ; <i64> [#uses=1]
        %1 = trunc i64 %0 to i32                ; <i32> [#uses=1]
        %2 = sext i32 %1 to i64         ; <i64> [#uses=1]
        store i64 %2, i64* %retval, align 8
        br label %return

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

Obviously the generated code is not incorrect, but it likely results in less
efficient code on targets without a native 64-bit multiplication instruction.

As the CellSPU does not have such a native 64-bit multiplication instruction,
i64 muls are turned into library calls to the _muldi3 function of libgcc, which
is supposed to perform 64-bit multiplications in software by using several
32-bit multiplications. However, as libgcc is compiled with -O2 by default
(which includes instcombine) the 32-bit multiplications in _muldi3 are promoted
to 64-bit multiplications, which is clearly not useful in this case :)


-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list