5

I have a piece of code that I'm trying to turn into LLVM bitcode:

int main() {
    volatile double n = 0.45;
    for (int j = 0; j < 32; j++) {
        n *= j;
    }
    return 0;
}

I run the following command on it:

clang -O0 -S -emit-llvm TrainingCode/trainingCode.cpp -o TrainingCode/trainingCode.ll

to generate the following LLVM bitcode (take note of the 6th line, the one with "Function Attrs"):

; ModuleID = 'TrainingCode/trainingCode.cpp'
source_filename = "TrainingCode/trainingCode.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: noinline norecurse nounwind optnone uwtable
define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %n = alloca double, align 8
  %j = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store double 4.500000e-01, double* %n, align 8
  store i32 0, i32* %j, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %0 = load i32, i32* %j, align 4
  %cmp = icmp slt i32 %0, 32
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %1 = load i32, i32* %j, align 4
  %conv = sitofp i32 %1 to double
  %2 = load double, double* %n, align 8
  %mul = fmul double %2, %conv
  store double %mul, double* %n, align 8
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %3 = load i32, i32* %j, align 4
  %inc = add nsw i32 %3, 1
  store i32 %inc, i32* %j, align 4
  br label %for.cond

for.end:                                          ; preds = %for.cond
  ret i32 0
}

attributes #0 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.0 (tags/RELEASE_500/final)"}

Why is clang adding the optnone attribute to main? I need LLVM to run various transformation passes on the bitcode and the optnone attribute is causing LLVM to skip over main... I need this attribute to not be added.

Compiling with -O1 seems to fix this, however this is unacceptable because I need Clang to give me unoptimized code. I want LLVM to optimize the unoptimized code given to me by Clang, but the presence of the optnone attribute is causing LLVM to not perform any optimizations.

10
  • 1
    Then why is it a problem that you have optnone? Commented Nov 27, 2017 at 5:06
  • 1
    @Justin Because I want LLVM to optimize the unoptimized code given to me by Clang, but the presence of the the optnone attribute is causing LLVM to not perform any optimizations. Commented Nov 27, 2017 at 5:07
  • 1
    I can't imagine a production scenario where that would be useful.... Why would you want to run LLVM separately? Regardless, what you could do is compile twice, once with optimizations and once without. Commented Nov 27, 2017 at 5:09
  • 2
    @Justin It's not a production scenario, I'm doing research into compiler optimization techniques using LLVM and need unoptimized bitcode to do this. How would compiling twice solve my problem? I would then have unoptimized code with the attribute and optimized code without it, neither of which is useful to me... Commented Nov 27, 2017 at 5:11
  • 1
    I think the reason for this is so clang can use the correct optimization level for each function when doing LTO. Commented Nov 27, 2017 at 8:45

3 Answers 3

11

There are clang options to disable its optimization of the LLVM-IR. See https://reviews.llvm.org/D28047 for discussion of a patch that would change them, and @Anton's answer to this question for more about using it. Some or all of these options might be the right thing:

clang -O1 -mllvm -disable-llvm-optzns -disable-llvm-passes

(The resolution of that discussion was commit rL290392: Make '-disable-llvm-optzns' an alias for '-disable-llvm-passes', so current clang only needs one.)


Or there's the dumb way: A simple workaround is possible with sed (or your favourite text-processing tool).

You're only using this on compiler-generated code, so you don't have to worry about using regexes to parse free-form hand-written code. Thus you can match fixed formatting that the compiler always uses to make sure you operate only on the correct lines.

# tested and works on the .ll in your question
sed -i '/^; Function Attrs:\|^attributes #/ s/optnone //'   *.ll

Replaces the first occurence of optnone (with a trailing space) with the empty string, on lines that start with attributes # (the one that matters) or with ; Function Attrs: (the comment).

It's an s/// command controlled by a /foo\|bar/ address regex to select which lines it operates on.

sed -i rewrites the input file(s) in-place.

Sign up to request clarification or add additional context in comments.

Comments

5

This is expected. The -O0 output is not intended for further optimizations, some bits of IR are not emitted at all in order to reduce the compilation time.

So, you'd need to use -O1 -mllvm -disable-llvm-optzns if you want to get unoptimized IR that may be optimized later.

1 Comment

Ah, yes a clang patch review mentions this option and describes it as "what you want to get raw LLVM-IR out of clang". reviews.llvm.org/D28047. See also discussion on that patch review re the related -disable-llvm-passes; you might want both in older clang, and I didn't read carefully to see what they decided to do.
3

Sorry not a solution, but maybe a clue.

But be clang version released or environment variables.

Taking your code on OS X with XCODE 9:

$ clang -O0 -S -emit-llvm test.cpp  -o test2.ll

$ more test2.ll
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"

; Function Attrs: norecurse nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca double, align 8

...

; <label>:15:                                     ; preds = %4
  ret i32 0
}

attributes #0 = { norecurse nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 8.1.0 (clang-802.0.42)"}

1 Comment

So somewhere in Apple's version of clang, there's a patch that makes it leave out the optnone attribute? Maybe worth checking on gcc.godbolt.org to see if newer or older mainline clang versions are like that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.