<div dir="ltr">using `opt --print-after-all -O3` I see that EarlyCSE is interpreting the call to `ceil` and constant fold:<div><br></div><div><div>*** IR Dump After Early CSE ***</div><div>; Function Attrs: nobuiltin nounwind</div><div>define i1 @do_test() #2 {</div><div>Entry:</div><div>  %0 = call fastcc float @ceil(float 0.000000e+00) #6</div><div>  %1 = call fastcc float @ceil32(float 0.000000e+00) #6</div><div>  %2 = fcmp fast oeq float 0.000000e+00, %1</div><div>  ret i1 %2</div><div>}</div></div><div><br></div><div>So just running `opt -early-cse -debug` seems enough:</div><div><br></div><div><div>EarlyCSE Simplify:   %0 = call fastcc float @ceil(float 0.000000e+00) #6  to: float 0.000000e+00</div></div><div><br></div><div>I suspect it is not correct from EarlyCSE to do that.</div><div><br></div><div>-- </div><div>Mehdi</div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2017-06-19 9:27 GMT-07:00 Andrew Kelley <span dir="ltr"><<a href="mailto:superjoe30@gmail.com" target="_blank">superjoe30@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Oops. Pressed send on accident.<span class=""><div><br></div><div>With -O3, the module gets rewritten to:</div></span><div><div>; Function Attrs: nobuiltin nounwind</div><div>define i1 @do_test() local_unnamed_addr #0 !dbg !16 {</div><div>Entry:</div><div>  %x.sroa.0.i.i = alloca i32, align 4</div><div>  %x.sroa.0.i.i.i = alloca i32, align 4</div><div>  tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !21, metadata !28) #3, !dbg !29</div><div>  tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !32, metadata !28) #3, !dbg !44</div><div>  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !35, metadata !28) #3, !dbg !49</div><div>  tail call void @llvm.dbg.value(metadata i32 -127, i64 0, metadata !39, metadata !28) #3, !dbg !50</div><div>  %x.sroa.0.i.i.i.0.sroa_cast = bitcast i32* %x.sroa.0.i.i.i to i8*, !dbg !51</div><div>  call void @llvm.lifetime.start(i64 4, i8* nonnull %x.sroa.0.i.i.i.0.sroa_cast), !dbg !51</div><div>  tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !57, metadata !28) #3, !dbg !51</div><div>  tail call void @llvm.dbg.value(metadata float* undef, i64 0, metadata !61, metadata !28) #3, !dbg !67</div><div>  %x.sroa.0.i.i.i.0.x.sroa.0.i.<wbr>i.0.x.sroa.0.i.0.x.sroa.0.0.x.<wbr>sroa.0.0.x.0.1.i.i.i = load i32, i32* %x.sroa.0.i.i.i, align 4, !dbg !68</div><div>  store volatile i32 %x.sroa.0.i.i.i.0.x.sroa.0.i.<wbr>i.0.x.sroa.0.i.0.x.sroa.0.0.x.<wbr>sroa.0.0.x.0.1.i.i.i, i32* %x.sroa.0.i.i.i, align 4, !dbg !70</div><div>  call void @llvm.lifetime.end(i64 4, i8* nonnull %x.sroa.0.i.i.i.0.sroa_cast), !dbg !71</div><div>  tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !32, metadata !28) #3, !dbg !72</div><div>  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !35, metadata !28) #3, !dbg !75</div><div>  tail call void @llvm.dbg.value(metadata i32 -127, i64 0, metadata !39, metadata !28) #3, !dbg !76</div><div>  %x.sroa.0.i.i.0.sroa_cast = bitcast i32* %x.sroa.0.i.i to i8*, !dbg !77</div><div>  call void @llvm.lifetime.start(i64 4, i8* nonnull %x.sroa.0.i.i.0.sroa_cast), !dbg !77</div><div>  tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !57, metadata !28) #3, !dbg !77</div><div>  tail call void @llvm.dbg.value(metadata float* undef, i64 0, metadata !61, metadata !28) #3, !dbg !79</div><div>  %x.sroa.0.i.i.0.x.sroa.0.i.0.<wbr>x.sroa.0.0.x.sroa.0.0.x.0.1.i.<wbr>i = load i32, i32* %x.sroa.0.i.i, align 4, !dbg !80</div><div>  store volatile i32 %x.sroa.0.i.i.0.x.sroa.0.i.0.<wbr>x.sroa.0.0.x.sroa.0.0.x.0.1.i.<wbr>i, i32* %x.sroa.0.i.i, align 4, !dbg !81</div><div>  call void @llvm.lifetime.end(i64 4, i8* nonnull %x.sroa.0.i.i.0.sroa_cast), !dbg !82</div><div>  ret i1 false, !dbg !83</div><div>}</div></div><div><br></div><div><br></div><div>Note the `ret i1 false` at the end. Expected it to return true.</div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jun 19, 2017 at 12:26 PM, Andrew Kelley <span dir="ltr"><<a href="mailto:superjoe30@gmail.com" target="_blank">superjoe30@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span>On Mon, Jun 19, 2017 at 12:06 PM, Mehdi AMINI <span dir="ltr"><<a href="mailto:joker.eph@gmail.com" target="_blank">joker.eph@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi,<div class="gmail_extra"><br><div class="gmail_quote"><span class="m_6266148832678681205m_-3302502353943955379gmail-">2017-06-19 8:45 GMT-07:00 Andrew Kelley via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Greetings,</div><div><br></div><div>I have a Zig implementation of ceil which is emitted into LLVM IR like this:</div><div><br></div><div><div>; Function Attrs: nobuiltin nounwind</div><div>define internal fastcc float @ceil(float) unnamed_addr #3 !dbg !644 {</div><div>Entry:</div><div>  %x = alloca float, align 4</div><div>  store float %0, float* %x</div><div>  call void @llvm.dbg.declare(metadata float* %x, metadata !649, metadata !494), !dbg !651</div><div>  %1 = load float, float* %x, !dbg !652</div><div>  %2 = call fastcc float @ceil32(float %1) #8, !dbg !656</div><div>  ret float %2, !dbg !657</div><div>}</div></div><div><br></div><div>Test case:</div><div><br></div><div><div>test "math.ceil" {</div><div>    assert(ceil(f32(0.0)) == ceil32(0.0));</div><div>    assert(ceil(f64(0.0)) == ceil64(0.0));</div><div>}</div></div><div><br></div><div><br></div><div>When I compile with optimizations on, this test case fails. The optimized code for the test case ends up being a call to panic (assertion failure), which means that LLVM determined the test failed at compile-time.</div><div><br></div><div>What's strange about this is that if I change the function name from @ceil to @ceil_asdf (and change the callers) then the test passes.</div><div><br></div><div>So I think LLVM is doing some kind of string comparison on the symbol name and detecting that it is "ceil" and then having different, undesired behavior.</div><div><br></div><div>I tried putting `nobuiltin` in the function attributes and at the callsite, but that did not change anything.</div><div><br></div><div>Any ideas what's going on?</div></div></blockquote><div><br></div></span><div>I think it'd be a lot easier to figure if you provide a standalone repro.</div></div></div></div></blockquote><div><br></div></span><div>Standalone repro:</div><div><br></div><div><div>; ModuleID = 'test'</div><div>source_filename = "test"</div><div>target datalayout = "e-m:e-i64:64-f80:128-n8:16:32<wbr>:64-S128"</div><div>target triple = "x86_64-unknown-linux-gnu"</div><div><br></div><div>%"[]u8" = type { i8*, i64 }</div><div><br></div><div>@__zig_panic_implementation_pr<wbr>ovided = internal unnamed_addr constant i1 true, align 1</div><div><br></div><div>; Function Attrs: nounwind</div><div>declare void @llvm.debugtrap() #0</div><div><br></div><div>; Function Attrs: argmemonly nounwind</div><div>declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1</div><div><br></div><div>; Function Attrs: argmemonly nounwind</div><div>declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #1</div><div><br></div><div>; Function Attrs: nobuiltin nounwind</div><div>define i1 @do_test() #2 !dbg !16 {</div><div>Entry:</div><div>  %0 = call fastcc float @ceil(float 0.000000e+00) #6, !dbg !21</div><div>  %1 = call fastcc float @ceil32(float 0.000000e+00) #6, !dbg !23</div><div>  %2 = fcmp fast oeq float %0, %1, !dbg !24</div><div>  ret i1 %2, !dbg !25</div><div>}</div><div><br></div><div>; Function Attrs: cold nobuiltin noreturn nounwind</div><div>define linkonce coldcc void @__zig_panic(i8* nonnull readonly, i64) #3 !dbg !26 {</div><div>Entry:</div><div>  %2 = alloca %"[]u8", align 8</div><div>  %message_ptr = alloca i8*, align 8</div><div>  %message_len = alloca i64, align 8</div><div>  store i8* %0, i8** %message_ptr</div><div>  call void @llvm.dbg.declare(metadata i8** %message_ptr, metadata !34, metadata !37), !dbg !38</div><div>  store i64 %1, i64* %message_len</div><div>  call void @llvm.dbg.declare(metadata i64* %message_len, metadata !35, metadata !37), !dbg !39</div><div>  %3 = load i64, i64* %message_len, !dbg !40</div><div>  %4 = load i8*, i8** %message_ptr, !dbg !44</div><div>  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 0, !dbg !44</div><div>  %6 = getelementptr inbounds i8, i8* %4, i64 0, !dbg !44</div><div>  store i8* %6, i8** %5, !dbg !44</div><div>  %7 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 1, !dbg !44</div><div>  %8 = sub nsw i64 %3, 0, !dbg !44</div><div>  store i64 %8, i64* %7, !dbg !44</div><div>  call fastcc void @panic(%"[]u8"* byval %2) #6, !dbg !45</div><div>  unreachable, !dbg !45</div><div>}</div><div><br></div><div>; Function Attrs: nobuiltin nounwind</div><div>define internal fastcc float @ceil(float) unnamed_addr #2 !dbg !46 {</div><span><div>Entry:</div><div>  %x = alloca float, align 4</div><div>  store float %0, float* %x</div></span><div>  call void @llvm.dbg.declare(metadata float* %x, metadata !51, metadata !37), !dbg !53</div><div>  %1 = load float, float* %x, !dbg !54</div><div>  %2 = call fastcc float @ceil32(float %1) #7, !dbg !58</div><div>  ret float %2, !dbg !59</div><div>}</div><div><br></div><div>; Function Attrs: nobuiltin nounwind</div><div>define internal fastcc float @ceil32(float) unnamed_addr #2 !dbg !60 {</div><span><div>Entry:</div><div>  %x = alloca float, align 4</div></span><span><div>  %u = alloca i32, align 4</div><div>  %e = alloca i32, align 4</div></span><div>  %m = alloca i32, align 4</div><span><div>  store float %0, float* %x</div></span><div>  call void @llvm.dbg.declare(metadata float* %x, metadata !62, metadata !37), !dbg !72</div><div>  %1 = load float, float* %x, !dbg !73</div><div>  %2 = bitcast float %1 to i32, !dbg !74</div><div>  store i32 %2, i32* %u, !dbg !75</div><div>  call void @llvm.dbg.declare(metadata i32* %u, metadata !63, metadata !37), !dbg !75</div><div>  %3 = load i32, i32* %u, !dbg !76</div><div>  %4 = lshr i32 %3, 23, !dbg !77</div><div>  %5 = and i32 %4, 255, !dbg !78</div><div>  %6 = sub nsw i32 %5, 127, !dbg !79</div><div>  store i32 %6, i32* %e, !dbg !80</div><div>  call void @llvm.dbg.declare(metadata i32* %e, metadata !67, metadata !37), !dbg !80</div><div>  call void @llvm.dbg.declare(metadata i32* %m, metadata !70, metadata !37), !dbg !81</div><div>  %7 = load i32, i32* %e, !dbg !82</div><div>  %8 = icmp sge i32 %7, 23, !dbg !84</div><div>  br i1 %8, label %Then, label %Else, !dbg !84</div><div><br></div><div>Then:                                             ; preds = %Entry</div><div>  %9 = load float, float* %x, !dbg !85</div><div>  ret float %9, !dbg !87</div><div><br></div><div>Else:                                             ; preds = %Entry</div><div>  %10 = load i32, i32* %e, !dbg !88</div><div>  %11 = icmp sge i32 %10, 0, !dbg !89</div><div>  br i1 %11, label %Then1, label %Else2, !dbg !89</div><div><br></div><div>Then1:                                            ; preds = %Else</div><div>  %12 = load i32, i32* %e, !dbg !90</div><div>  %13 = lshr i32 8388607, %12, !dbg !92</div><div>  store i32 %13, i32* %m, !dbg !93</div><div>  %14 = load i32, i32* %u, !dbg !94</div><div>  %15 = load i32, i32* %m, !dbg !95</div><div>  %16 = and i32 %14, %15, !dbg !96</div><div>  %17 = icmp eq i32 %16, 0, !dbg !97</div><div>  br i1 %17, label %Then3, label %Else4, !dbg !97</div><div><br></div><div>Else2:                                            ; preds = %Else</div><div>  %18 = load float, float* %x, !dbg !98</div><div>  %19 = fadd fast float %18, 0x4770000000000000, !dbg !100</div><div>  call fastcc void @forceEval(float %19) #6, !dbg !101</div><div>  %20 = load i32, i32* %u, !dbg !102</div><div>  %21 = lshr i32 %20, 31, !dbg !103</div><div>  %22 = icmp ne i32 %21, 0, !dbg !104</div><div>  br i1 %22, label %Then5, label %Else6, !dbg !104</div><div><br></div><div>Then3:                                            ; preds = %Then1</div><div>  %23 = load float, float* %x, !dbg !105</div><div>  ret float %23, !dbg !107</div><div><br></div><div>Else4:                                            ; preds = %Then1</div><div>  br label %EndIf, !dbg !108</div><div><br></div><div>Then5:                                            ; preds = %Else2</div><div>  ret float -0.000000e+00, !dbg !109</div><div><br></div><div>Else6:                                            ; preds = %Else2</div><div>  br label %EndIf7, !dbg !111</div><div><br></div><div>EndIf:                                            ; preds = %Else4</div><div>  %24 = load float, float* %x, !dbg !112</div><div>  %25 = fadd fast float %24, 0x4770000000000000, !dbg !113</div><div>  call fastcc void @forceEval(float %25) #6, !dbg !114</div><div>  %26 = load i32, i32* %u, !dbg !115</div><div>  %27 = lshr i32 %26, 31, !dbg !116</div><div>  %28 = icmp eq i32 %27, 0, !dbg !117</div><div>  br i1 %28, label %Then8, label %Else9, !dbg !117</div><div><br></div><div>EndIf7:                                           ; preds = %Else6</div><div>  br label %EndIf11, !dbg !118</div><div><br></div><div>Then8:                                            ; preds = %EndIf</div><div>  %29 = load i32, i32* %u, !dbg !119</div><div>  %30 = load i32, i32* %m, !dbg !121</div><div>  %31 = add nuw i32 %29, %30, !dbg !122</div><div>  store i32 %31, i32* %u, !dbg !122</div><div>  br label %EndIf10, !dbg !123</div><div><br></div><div>Else9:                                            ; preds = %EndIf</div><div>  br label %EndIf10, !dbg !123</div><span><div><br></div><div>EndIf10:                                          ; preds = %Else9, %Then8</div></span><div>  %32 = load i32, i32* %u, !dbg !124</div><div>  %33 = load i32, i32* %m, !dbg !125</div><div>  %34 = xor i32 %33, -1, !dbg !126</div><div>  %35 = and i32 %32, %34, !dbg !127</div><div>  store i32 %35, i32* %u, !dbg !127</div><div>  %36 = load i32, i32* %u, !dbg !128</div><div>  %37 = bitcast i32 %36 to float, !dbg !129</div><div>  br label %EndIf11, !dbg !118</div><span><div><br></div><div>EndIf11:                                          ; preds = %EndIf10, %EndIf7</div></span><div>  %38 = phi float [ %37, %EndIf10 ], [ 1.000000e+00, %EndIf7 ], !dbg !118</div><div>  ret float %38, !dbg !130</div><div>}</div><div><br></div><div>; Function Attrs: nobuiltin noreturn nounwind</div><div>define internal fastcc void @panic(%"[]u8"* byval nonnull readonly) unnamed_addr #4 !dbg !131 {</div><div>Entry:</div><div>  call void @llvm.dbg.declare(metadata %"[]u8"* %0, metadata !141, metadata !37), !dbg !142</div><div>  call void @llvm.debugtrap(), !dbg !143</div><div>  br label %WhileCond, !dbg !146</div><div><br></div><div>WhileCond:                                        ; preds = %WhileCond, %Entry</div><div>  br label %WhileCond, !dbg !146</div><div>}</div><div><br></div><div>; Function Attrs: nobuiltin nounwind</div><div>define internal fastcc void @forceEval(float) unnamed_addr #2 !dbg !147 {</div><div>Entry:</div><div>  %value = alloca float, align 4</div><span><div>  %x = alloca float, align 4</div></span><span><div>  %p = alloca float*, align 8</div><div>  store float %0, float* %value</div></span><div>  call void @llvm.dbg.declare(metadata float* %value, metadata !151, metadata !37), !dbg !158</div><div>  call void @llvm.dbg.declare(metadata float* %x, metadata !152, metadata !37), !dbg !159</div><div>  store float* %x, float** %p, !dbg !160</div><div>  call void @llvm.dbg.declare(metadata float** %p, metadata !155, metadata !37), !dbg !160</div><div>  %1 = load float*, float** %p, !dbg !161</div><div>  %2 = load float, float* %x, !dbg !163</div><div>  store volatile float %2, float* %1, !dbg !164</div><div>  ret void, !dbg !165</div><div>}</div><div><br></div><div>; Function Attrs: nounwind readnone</div><div>declare void @llvm.dbg.declare(metadata, metadata, metadata) #5</div><div><br></div><div>attributes #0 = { nounwind }</div><div>attributes #1 = { argmemonly nounwind }</div><div>attributes #2 = { nobuiltin nounwind }</div><div>attributes #3 = { cold nobuiltin noreturn nounwind }</div><div>attributes #4 = { nobuiltin noreturn nounwind }</div><div>attributes #5 = { nounwind readnone }</div><div>attributes #6 = { nobuiltin }</div><div>attributes #7 = { alwaysinline nobuiltin }</div><div><br></div><div>!llvm.module.flags = !{!0}</div><div>!<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{!1}</div><div><br></div><div>!0 = !{i32 2, !"Debug Info Version", i32 3}</div><div>!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "zig 0.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !12)</div><div>!2 = !DIFile(filename: "test", directory: ".")</div><div>!3 = !{!4}</div><div>!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "GlobalLinkage", scope: !5, file: !5, line: 126, baseType: !6, size: 8, align: 8, elements: !7)</div><div>!5 = !DIFile(filename: "builtin.zig", directory: "/home/andy/dev/zig/build/zig-<wbr>cache")</div><div>!6 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned_char)</div><div>!7 = !{!8, !9, !10, !11}</div><div>!8 = !DIEnumerator(name: "Internal", value: 0)</div><div>!9 = !DIEnumerator(name: "Strong", value: 1)</div><div>!10 = !DIEnumerator(name: "Weak", value: 2)</div><div>!11 = !DIEnumerator(name: "LinkOnce", value: 3)</div><div>!12 = !{!13}</div><div>!13 = !DIGlobalVariableExpression(va<wbr>r: !14)</div><div>!14 = distinct !DIGlobalVariable(name: "__zig_panic_implementation_pr<wbr>ovided", linkageName: "__zig_panic_implementation_pr<wbr>ovided", scope: !5, file: !5, line: 189, type: !15, isLocal: true, isDefinition: true)</div><div>!15 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)</div><div>!16 = distinct !DISubprogram(name: "do_test", scope: !17, file: !17, line: 46, type: !18, isLocal: false, isDefinition: true, scopeLine: 46, isOptimized: true, unit: !1, variables: !20)</div><div>!17 = !DIFile(filename: "test.zig", directory: "/home/andy/dev/zig/build")</div><div>!18 = !DISubroutineType(types: !19)</div><div>!19 = !{!15}</div><div>!20 = !{}</div><div>!21 = !DILocation(line: 47, column: 16, scope: !22)</div><div>!22 = distinct !DILexicalBlock(scope: !16, file: !17, line: 46, column: 29)</div><div>!23 = !DILocation(line: 47, column: 36, scope: !22)</div><div>!24 = !DILocation(line: 47, column: 27, scope: !22)</div><div>!25 = !DILocation(line: 47, column: 5, scope: !22)</div><div>!26 = distinct !DISubprogram(name: "__zig_panic", scope: !27, file: !27, line: 7, type: !28, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: true, unit: !1, variables: !33)</div><div>!27 = !DIFile(filename: "zigrt.zig", directory: "/home/andy/dev/zig/build/lib/<wbr>zig/std/special")</div><div>!28 = !DISubroutineType(types: !29)</div><div>!29 = !{!30, !31, !32}</div><div>!30 = !DIBasicType(name: "void", encoding: DW_ATE_unsigned)</div><div>!31 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&const u8", baseType: !6, size: 64, align: 64)</div><div>!32 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned)</div><div>!33 = !{!34, !35}</div><div>!34 = !DILocalVariable(name: "message_ptr", arg: 1, scope: !26, file: !27, line: 7, type: !31)</div><div>!35 = !DILocalVariable(name: "message_len", arg: 2, scope: !36, file: !27, line: 7, type: !32)</div><div>!36 = distinct !DILexicalBlock(scope: !26, file: !27, line: 7, column: 30)</div><div>!37 = !DIExpression()</div><div>!38 = !DILocation(line: 7, column: 30, scope: !26)</div><div>!39 = !DILocation(line: 7, column: 54, scope: !36)</div><div>!40 = !DILocation(line: 12, column: 48, scope: !41)</div><div>!41 = distinct !DILexicalBlock(scope: !42, file: !27, line: 11, column: 54)</div><div>!42 = distinct !DILexicalBlock(scope: !43, file: !27, line: 7, column: 86)</div><div>!43 = distinct !DILexicalBlock(scope: !36, file: !27, line: 7, column: 54)</div><div>!44 = !DILocation(line: 12, column: 43, scope: !41)</div><div>!45 = !DILocation(line: 12, column: 31, scope: !41)</div><div>!46 = distinct !DISubprogram(name: "ceil", scope: !17, file: !17, line: 3, type: !47, isLocal: true, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !1, variables: !50)</div><div>!47 = !DISubroutineType(types: !48)</div><div>!48 = !{!49, !49}</div><div>!49 = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)</div><div>!50 = !{!51}</div><div>!51 = !DILocalVariable(name: "x", arg: 1, scope: !52, file: !17, line: 3, type: !49)</div><div>!52 = distinct !DILexicalBlock(scope: !46, file: !17, line: 3, column: 13)</div><div>!53 = !DILocation(line: 3, column: 13, scope: !52)</div><div>!54 = !DILocation(line: 6, column: 36, scope: !55)</div><div>!55 = distinct !DILexicalBlock(scope: !56, file: !17, line: 4, column: 5)</div><div>!56 = distinct !DILexicalBlock(scope: !57, file: !17, line: 3, column: 35)</div><div>!57 = distinct !DILexicalBlock(scope: !52, file: !17, line: 3, column: 13)</div><div>!58 = !DILocation(line: 6, column: 16, scope: !55)</div><div>!59 = !DILocation(line: 5, column: 5, scope: !57)</div><div>!60 = distinct !DISubprogram(name: "ceil32", scope: !17, file: !17, line: 11, type: !47, isLocal: true, isDefinition: true, scopeLine: 11, isOptimized: true, unit: !1, variables: !61)</div><div>!61 = !{!62, !63, !67, !70}</div><div>!62 = !DILocalVariable(name: "x", arg: 1, scope: !60, file: !17, line: 11, type: !49)</div><div>!63 = !DILocalVariable(name: "u", scope: !64, file: !17, line: 12, type: !66)</div><div>!64 = distinct !DILexicalBlock(scope: !65, file: !17, line: 11, column: 26)</div><div>!65 = distinct !DILexicalBlock(scope: !60, file: !17, line: 11, column: 11)</div><div>!66 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)</div><div>!67 = !DILocalVariable(name: "e", scope: !68, file: !17, line: 13, type: !69)</div><div>!68 = distinct !DILexicalBlock(scope: !64, file: !17, line: 12, column: 5)</div><div>!69 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)</div><div>!70 = !DILocalVariable(name: "m", scope: !71, file: !17, line: 14, type: !66)</div><div>!71 = distinct !DILexicalBlock(scope: !68, file: !17, line: 13, column: 5)</div><div>!72 = !DILocation(line: 11, column: 11, scope: !60)</div><div>!73 = !DILocation(line: 12, column: 27, scope: !64)</div><div>!74 = !DILocation(line: 12, column: 13, scope: !64)</div><div>!75 = !DILocation(line: 12, column: 5, scope: !64)</div><div>!76 = !DILocation(line: 13, column: 18, scope: !68)</div><div>!77 = !DILocation(line: 13, column: 20, scope: !68)</div><div>!78 = !DILocation(line: 13, column: 27, scope: !68)</div><div>!79 = !DILocation(line: 13, column: 35, scope: !68)</div><div>!80 = !DILocation(line: 13, column: 5, scope: !68)</div><div>!81 = !DILocation(line: 14, column: 5, scope: !71)</div><div>!82 = !DILocation(line: 16, column: 9, scope: !83)</div><div>!83 = distinct !DILexicalBlock(scope: !71, file: !17, line: 14, column: 5)</div><div>!84 = !DILocation(line: 16, column: 11, scope: !83)</div><div>!85 = !DILocation(line: 17, column: 16, scope: !86)</div><div>!86 = distinct !DILexicalBlock(scope: !83, file: !17, line: 16, column: 18)</div><div>!87 = !DILocation(line: 17, column: 9, scope: !86)</div><div>!88 = !DILocation(line: 19, column: 14, scope: !83)</div><div>!89 = !DILocation(line: 19, column: 16, scope: !83)</div><div>!90 = !DILocation(line: 20, column: 31, scope: !91)</div><div>!91 = distinct !DILexicalBlock(scope: !83, file: !17, line: 19, column: 22)</div><div>!92 = !DILocation(line: 20, column: 24, scope: !91)</div><div>!93 = !DILocation(line: 20, column: 11, scope: !91)</div><div>!94 = !DILocation(line: 21, column: 13, scope: !91)</div><div>!95 = !DILocation(line: 21, column: 17, scope: !91)</div><div>!96 = !DILocation(line: 21, column: 15, scope: !91)</div><div>!97 = !DILocation(line: 21, column: 19, scope: !91)</div><div>!98 = !DILocation(line: 31, column: 19, scope: !99)</div><div>!99 = distinct !DILexicalBlock(scope: !83, file: !17, line: 30, column: 12)</div><div>!100 = !DILocation(line: 31, column: 21, scope: !99)</div><div>!101 = !DILocation(line: 31, column: 18, scope: !99)</div><div>!102 = !DILocation(line: 32, column: 13, scope: !99)</div><div>!103 = !DILocation(line: 32, column: 15, scope: !99)</div><div>!104 = !DILocation(line: 32, column: 21, scope: !99)</div><div>!105 = !DILocation(line: 22, column: 20, scope: !106)</div><div>!106 = distinct !DILexicalBlock(scope: !91, file: !17, line: 21, column: 25)</div><div>!107 = !DILocation(line: 22, column: 13, scope: !106)</div><div>!108 = !DILocation(line: 21, column: 9, scope: !91)</div><div>!109 = !DILocation(line: 33, column: 13, scope: !110)</div><div>!110 = distinct !DILexicalBlock(scope: !99, file: !17, line: 32, column: 27)</div><div>!111 = !DILocation(line: 32, column: 9, scope: !99)</div><div>!112 = !DILocation(line: 24, column: 19, scope: !91)</div><div>!113 = !DILocation(line: 24, column: 21, scope: !91)</div><div>!114 = !DILocation(line: 24, column: 18, scope: !91)</div><div>!115 = !DILocation(line: 25, column: 13, scope: !91)</div><div>!116 = !DILocation(line: 25, column: 15, scope: !91)</div><div>!117 = !DILocation(line: 25, column: 21, scope: !91)</div><div>!118 = !DILocation(line: 19, column: 10, scope: !83)</div><div>!119 = !DILocation(line: 26, column: 13, scope: !120)</div><div>!120 = distinct !DILexicalBlock(scope: !91, file: !17, line: 25, column: 27)</div><div>!121 = !DILocation(line: 26, column: 18, scope: !120)</div><div>!122 = !DILocation(line: 26, column: 15, scope: !120)</div><div>!123 = !DILocation(line: 25, column: 9, scope: !91)</div><div>!124 = !DILocation(line: 28, column: 9, scope: !91)</div><div>!125 = !DILocation(line: 28, column: 15, scope: !91)</div><div>!126 = !DILocation(line: 28, column: 14, scope: !91)</div><div>!127 = !DILocation(line: 28, column: 11, scope: !91)</div><div>!128 = !DILocation(line: 29, column: 23, scope: !91)</div><div>!129 = !DILocation(line: 29, column: 9, scope: !91)</div><div>!130 = !DILocation(line: 16, column: 5, scope: !65)</div><div>!131 = distinct !DISubprogram(name: "panic", scope: !17, file: !17, line: 1, type: !132, isLocal: true, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !1, variables: !140)</div><div>!132 = !DISubroutineType(types: !133)</div><div>!133 = !{!30, !134}</div><div>!134 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&const []const u8", baseType: !135, size: 64, align: 64)</div><div>!135 = !DICompositeType(tag: DW_TAG_structure_type, name: "[]u8", size: 128, align: 128, elements: !136)</div><div>!136 = !{!137, !139}</div><div>!137 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !135, baseType: !138, size: 64, align: 64)</div><div>!138 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !6, size: 64, align: 64)</div><div>!139 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !135, baseType: !32, size: 64, align: 64, offset: 64)</div><div>!140 = !{!141}</div><div>!141 = !DILocalVariable(name: "msg", arg: 1, scope: !131, file: !17, line: 1, type: !135)</div><div>!142 = !DILocation(line: 1, column: 14, scope: !131)</div><div>!143 = !DILocation(line: 1, column: 45, scope: !144)</div><div>!144 = distinct !DILexicalBlock(scope: !145, file: !17, line: 1, column: 43)</div><div>!145 = distinct !DILexicalBlock(scope: !131, file: !17, line: 1, column: 14)</div><div>!146 = !DILocation(line: 1, column: 60, scope: !144)</div><div>!147 = distinct !DISubprogram(name: "forceEval", scope: !17, file: !17, line: 39, type: !148, isLocal: true, isDefinition: true, scopeLine: 39, isOptimized: true, unit: !1, variables: !150)</div><div>!148 = !DISubroutineType(types: !149)</div><div>!149 = !{!30, !49}</div><div>!150 = !{!151, !152, !155}</div><div>!151 = !DILocalVariable(name: "value", arg: 1, scope: !147, file: !17, line: 39, type: !49)</div><div>!152 = !DILocalVariable(name: "x", scope: !153, file: !17, line: 40, type: !49)</div><div>!153 = distinct !DILexicalBlock(scope: !154, file: !17, line: 39, column: 30)</div><div>!154 = distinct !DILexicalBlock(scope: !147, file: !17, line: 39, column: 18)</div><div>!155 = !DILocalVariable(name: "p", scope: !156, file: !17, line: 41, type: !157)</div><div>!156 = distinct !DILexicalBlock(scope: !153, file: !17, line: 40, column: 5)</div><div>!157 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&volatile f32", baseType: !49, size: 64, align: 64)</div><div>!158 = !DILocation(line: 39, column: 18, scope: !147)</div><div>!159 = !DILocation(line: 40, column: 5, scope: !153)</div><div>!160 = !DILocation(line: 41, column: 5, scope: !156)</div><div>!161 = !DILocation(line: 42, column: 5, scope: !162)</div><div>!162 = distinct !DILexicalBlock(scope: !156, file: !17, line: 41, column: 5)</div><div>!163 = !DILocation(line: 42, column: 10, scope: !162)</div><div>!164 = !DILocation(line: 42, column: 8, scope: !162)</div><div>!165 = !DILocation(line: 39, column: 30, scope: !154)</div></div><div><br></div><div>source:</div><div><div>pub fn panic(msg: []const u8) -> noreturn { @breakpoint(); while (true) {} }</div><div><br></div><div>pub fn ceil(x: var) -> @typeOf(x) {</div><div>    const T = @typeOf(x);</div><div>    switch (T) {</div><div>        f32 => @inlineCall(ceil32, x),</div><div>        else => @compileError("ceil not implemented for " ++ @typeName(T)),</div><span><div>    }</div><div>}</div><div><br></div><div>fn ceil32(x: f32) -> f32 {</div><div>    var u = @bitCast(u32, x);</div><div>    var e = i32((u >> 23) & 0xFF) - 0x7F;</div><div>    var m: u32 = undefined;</div><div><br></div><div>    if (e >= 23) {</div><div>        return x;</div><div>    }</div><div>    else if (e >= 0) {</div><div>        m = 0x007FFFFF >> u32(e);</div><div>        if (u & m == 0) {</div><div>            return x;</div><div>        }</div></span><span><div>        forceEval(x + 0x1.0p120);</div><div>        if (u >> 31 == 0) {</div><div>            u += m;</div><div>        }</div><div>        u &= ~m;</div><div>        @bitCast(f32, u)</div><div>    } else {</div></span><span><div>        forceEval(x + 0x1.0p120);</div><div>        if (u >> 31 != 0) {</div><div>            return -0.0;</div><div>        } else {</div><div>            1.0</div><div>        }</div><div>    }</div><div>}</div></span><div>pub fn forceEval(value: f32) {</div><span><div>    var x: f32 = undefined;</div><div>    const p = @ptrCast(&volatile f32, &x);</div><div>    *p = x;</div><div>}</div><div><br></div><div><br></div></span><div>export fn do_test() -> bool {</div><div>    return ceil(f32(0.0)) == ceil32(0.0);</div><div>}</div></div><div><br></div><div><br></div><div>-----------------------</div><div><br></div><div>With no optimizations, the do_test function returns true, which is expected. With -O3, the module gets rewritten to:</div><div><br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="m_6266148832678681205m_-3302502353943955379gmail-HOEnZb"><font color="#888888"><div><br></div><span class="m_6266148832678681205HOEnZb"><font color="#888888"><div>-- </div><div>Mehdi</div><div><br></div></font></span></font></span></div></div></div>
</blockquote></div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>