Skip to content

infinite loop optimized away unless function is exported #1658

Closed

Description

@numsim1415
export fn square(num: u8) u8 {
             
             //while(true){} // would generate loop
             return eternity(123); 
}

pub fn eternity(bla:u8) u8 {
  while(true)// is optimized away completely
  {}
}

See asm output on goldbold.
As you said during live coding, it seems like the eternal loop is considered to have no side effects and is thus removed.

Expected behaviour would be to refuse compilation

  • as there is no return of an u8
  • as in case of eternity being declared as returning void, an implicit return; at the end of the function cannot be reached

Activity

  1. added this to the 0.4.0 milestone on Oct 16, 2018
  2. added
    bugObserved behavior contradicts documented or intended behavior
    on Oct 16, 2018
  3. modified the milestones: 0.4.0, 0.5.0 on Apr 3, 2019
  4. modified the milestones: 0.5.0, 0.6.0 on Aug 27, 2019
  5. modified the milestones: 0.6.0, 0.7.0 on Dec 31, 2019
  6. IridescentRose commented on Oct 20, 2020

    @IridescentRose
    Contributor

    Isn't this a long time LLVM bug present in other languages like C and C++ where an empty infinite loop results in no consequences and thus creates invalid programs? (for example there are many articles like https://stackoverflow.com/questions/59925618/how-do-i-make-an-infinite-empty-loop-that-wont-be-optimized-away). I guess the solution Zig would need for this specific case is adding in a nop op-code inside of the loop so LLVM says it "has an effect" and doesn't generate an invalid program/function.

  7. IridescentRose commented on Oct 20, 2020

    @IridescentRose
    Contributor
     export fn square(num: u8) u8 {          
        //while(true){}
        return eternity(123); 
    }
    
    pub fn eternity(bla:u8) u8 {
        while(true){
            asm volatile("nop");
        }
    }

    This code generates as intended as we can see on GodBolt.

  8. modified the milestones: 0.7.0, 0.8.0 on Oct 30, 2020
  9. modified the milestones: 0.8.0, 0.8.1 on Jun 4, 2021
  10. modified the milestones: 0.8.1, 0.9.1 on Sep 1, 2021
  11. Sobeston commented on Sep 22, 2021

    @Sobeston
    Contributor

    Related: rust-lang/rust#82884 - apparently this was fixed in LLVM 12.

    export fn square(num: u8) u8 {
        _ = num;
        return eternity(123);
    }
    
    pub fn eternity(bla: u8) u8 {
        _ = bla;
        while (true) {}
    }
    
    export fn square2(num: u8) u8 {
        _ = num;
        while (true) {}
    }
    
    export fn square3() u8 {
        while (true) {}
    }

    This code, paired with zig build-obj on my master build of Zig (approx 1 week old) is producing while loops correctly in all three cases, in all four -O flags.

    image
    (pictured above: ReleaseSmall)

    pub fn main() void {
        while (true) {}
    }

    I've also tested this executable with all four -O flags, and this works on all of them.

  12. modified the milestones: 0.9.1, 0.9.0 on Nov 20, 2021
  13. added
    backend-llvmThe LLVM backend outputs an LLVM IR Module.
    upstreamAn issue with a third party project that Zig uses.
    on Nov 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend-llvmThe LLVM backend outputs an LLVM IR Module.bugObserved behavior contradicts documented or intended behaviorupstreamAn issue with a third party project that Zig uses.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions