Strange opt result

Hi,
opt -O1 converts the attached test.ll to test_opt.ll.
"
opt --version
LLVM (http://llvm.org/):
  LLVM version 3.8.0
  DEBUG build with assertions.
  Built Jun 23 2016 (18:32:09).
  Default target: i686-pc-linux-gnu
  Host CPU: k8-sse3
"

test.ll:
"
; ModuleID = 'test.bc'

@__mla__system.1 = global i32 0
@0 = internal global [12 x i8] zeroinitializer
@1 = internal global [8 x i8] zeroinitializer
@2 = internal constant [2 x i8] c"\0A\00"
@3 = internal constant [3 x i8] c"%u\00"
@4 = internal constant [5 x i8] c"%hhd\00"
@5 = internal constant [4 x i8] c"%hd\00"
@6 = internal constant [3 x i8] c"%d\00"
@7 = internal constant [5 x i8] c"%lld\00"
@8 = internal constant [3 x i8] c"%c\00"
@9 = internal constant [3 x i8] c"%s\00"
@10 = internal constant [3 x i8] c"%p\00"
@11 = internal constant [3 x i8] c"%e\00"

define internal [8 x i8] @12(i32, i8*) {
  %3 = alloca [8 x i8], i8 1
  %4 = alloca i32, i8 1
  %5 = alloca i8*, i8 1
  store i32 %0, i32* %4
  store i8* %1, i8** %5
  %6 = load i32, i32* %4
  %7 = bitcast [8 x i8]* %3 to i8*
  %8 = getelementptr inbounds i8, i8* %7, i8 0
  %9 = bitcast i8* %8 to i32*
  store i32 %6, i32* %9
  %10 = load i8*, i8** %5
  %11 = bitcast [8 x i8]* %3 to i8*
  %12 = getelementptr inbounds i8, i8* %11, i8 4
  %13 = bitcast i8* %12 to i8**
  store i8* %10, i8** %13
  %14 = load [8 x i8], [8 x i8]* %3
  ret [8 x i8] %14
}

define i32 @main() {
  %1 = bitcast i32 2 to i32
  %2 = bitcast [12 x i8]* @0 to i8*
  %3 = getelementptr inbounds i8, i8* %2, i8 0
  %4 = call [8 x i8] @12(i32 %1, i8* %3)
[...]
"

test_opt.ll:
"
; ModuleID = 'test_opt.bc'

@__mla__system.1 = global i32 0
@0 = internal global [12 x i8] zeroinitializer
@1 = internal unnamed_addr global [8 x i8] zeroinitializer

; Function Attrs: norecurse nounwind readnone
define internal fastcc [8 x i8] @2() unnamed_addr #0 {
  ret [8 x i8] [i8 2, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8
undef]
}

; Function Attrs: norecurse nounwind
define i32 @main() #1 {
  %1 = tail call fastcc [8 x i8] @2()
  store [8 x i8] %1, [8 x i8]* @1, align 1
  %2 = load i8*, i8** bitcast (i8* getelementptr inbounds ([8 x i8], [8 x i8]*
@1, i64 0, i64 4) to i8**), align 8
  %3 = icmp eq i8* %2, getelementptr inbounds ([12 x i8], [12 x i8]* @0, i64
0, i64 0)
  br i1 %3, label %5, label %4

; <label>:4 ; preds = %0
  store i32 1, i32* @__mla__system.1, align 4
  br label %5

; <label>:5 ; preds = %0, %4
  %6 = load i32, i32* @__mla__system.1, align 4
  ret i32 %6
}

attributes #0 = { norecurse nounwind readnone }
attributes #1 = { norecurse nounwind }
"

which looks incorrect to me and returns 1 instead of the expected 0 at
runtime. The testcase compiled without optimisation works as expected.
The input file has been produced with the MSElang compiler.

What is wrong?

Thanks, Martin

test.ll (2.31 KB)

test_opt.ll (1.04 KB)

You need to set a "target datalayout" and "target triple" before you run a
program through the optimizer. For example, for 32-bit Linux, clang
generates:

target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i386-unknown-linux-gnu"

If you don't do this, the optimizer will make bad assumptions; among other
things, it will assume pointers are 64-bit.

-Eli

That was it, thank you very much. :slight_smile:

Martin