[LLVMbugs] [Bug 13266] New: Kaleidoscope "for" loop codegen is semantically incorrect (Ch5-Ch7)
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Wed Jul 4 00:14:41 PDT 2012
http://llvm.org/bugs/show_bug.cgi?id=13266
Bug #: 13266
Summary: Kaleidoscope "for" loop codegen is semantically
incorrect (Ch5-Ch7)
Product: new-bugs
Version: trunk
Platform: All
OS/Version: All
Status: NEW
Severity: enhancement
Priority: P
Component: new bugs
AssignedTo: unassignedbugs at nondot.org
ReportedBy: harrism at gmail.com
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
Created attachment 8827
--> http://llvm.org/bugs/attachment.cgi?id=8827
Patch file to replace for loop codegen in Kaleidoscope tutorial Ch5-Ch7 (code
and docs). Patch created with "git diff --no-prefix > patchfile"
The implementation of for loops in the (excellent) Kaleidoscope tutorial
starting in Chapter 5 evaluates the end condition after executing the loop
body. This means that the body is always executed once even if the end
condition is initially false. The consequence is that it always executes one
iteration more than expected (based on the semantics of for loops in just about
any language). It's effectively a strange hybrid between a "for" loop and a
"do while" loop.
It might be OK to have Kaleidoscope's "for loops" to have unique semantics
given the limited feature set of the language. However, I am currently using
the Kaleidoscope interpreter code as a learning platform, and my first project
was to add arrays to the language. When iterating over arrays, it is dangerous
for the loop to go one step further than expected -- it can easily lead to a
buffer overrun, or crash (which is how I discovered this). Also, it makes for
unexpected behavior: the "printstars(n)" example in the tutorial prints 101
stars when n==100, and the "fibi(x)" example has different loop limits than
most similar implementations found on the web in other languages.
I have provided a fix for this issue in the attached patch (modified from
svn/git trunk), which fixes the code for chapters 5-7 as well as the HTML
documentation for the tutorial. I did not fix the OCaml implementation of the
tutorial. The fix is contained in the ForExprAST::Codegen() function, and
changes the output IR
from this:
declare double @putchard(double)
define double @printstar(double %n) {
entry:
; initial value = 1.0 (inlined into phi)
br label %loop
loop: ; preds = %loop, %entry
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
; body
%calltmp = call double @putchard(double 4.200000e+01)
; increment
%nextvar = fadd double %i, 1.000000e+00
; termination test
%cmptmp = fcmp ult double %i, %n
%booltmp = uitofp i1 %cmptmp to double
%loopcond = fcmp one double %booltmp, 0.000000e+00
br i1 %loopcond, label %loop, label %afterloop
afterloop: ; preds = %loop
; loop always returns 0.0
ret double 0.000000e+00
}
to this:
declare double @putchard(double)
define double @printstar(double %n) {
entry:
; initial value = 1.0 (inlined into phi)
br label %loop
loopstart: ; preds = %loopbody, %entry
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loopbody ]
; termination test
%cmptmp = fcmp ult double %i, %n
%booltmp = uitofp i1 %cmptmp to double
%loopcond = fcmp one double %booltmp, 0.000000e+00
br i1 %loopcond, label %loopbody, label %loopexit
loopbody: ; preds = %loopstart
; body
%calltmp = call double @putchard(double 4.200000e+01)
; increment
%nextvar = fadd double %i, 1.000000e+00
br label %loopstart
loopexit: ; preds = %loopstart
; loop always returns 0.0
ret double 0.000000e+00
}
Notice in the latter we first evaluate the end condition, and branch to the
loop body when it is true, and to the loop exit if false. The end of the loop
body is an unconditional branch back to the loop start. (This is the IR for
Ch5. For Ch7 there is an alloca/load/store rather than phi).
--
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