103 lines
5.4 KiB
Text
103 lines
5.4 KiB
Text
; This is not strictly LLVM, as it uses the C library function "printf".
|
|
; LLVM does not provide a way to print values, so the alternative would be
|
|
; to just load the string into memory, and that would be boring.
|
|
|
|
; Additional comments have been inserted, as well as changes made from the output produced by clang such as putting more meaningful labels for the jumps
|
|
|
|
$"ASSERTION" = comdat any
|
|
$"OUTPUT" = comdat any
|
|
|
|
@"ASSERTION" = linkonce_odr unnamed_addr constant [48 x i8] c"arithmetic-geometric mean undefined when x*y<0\0A\00", comdat, align 1
|
|
@"OUTPUT" = linkonce_odr unnamed_addr constant [42 x i8] c"The arithmetic-geometric mean is %0.19lf\0A\00", comdat, align 1
|
|
|
|
;--- The declarations for the external C functions
|
|
declare i32 @printf(i8*, ...)
|
|
declare void @exit(i32) #1
|
|
declare double @sqrt(double) #1
|
|
|
|
declare double @llvm.fabs.f64(double) #2
|
|
|
|
;----------------------------------------------------------------
|
|
;-- arithmetic geometric mean
|
|
define double @agm(double, double) #0 {
|
|
%3 = alloca double, align 8 ; allocate local g
|
|
%4 = alloca double, align 8 ; allocate local a
|
|
%5 = alloca double, align 8 ; allocate iota
|
|
%6 = alloca double, align 8 ; allocate a1
|
|
%7 = alloca double, align 8 ; allocate g1
|
|
store double %1, double* %3, align 8 ; store param g in local g
|
|
store double %0, double* %4, align 8 ; store param a in local a
|
|
store double 1.000000e-15, double* %5, align 8 ; store 1.0e-15 in iota (1.0e-16 was causing the program to hang)
|
|
|
|
%8 = load double, double* %4, align 8 ; load a
|
|
%9 = load double, double* %3, align 8 ; load g
|
|
%10 = fmul double %8, %9 ; a * g
|
|
%11 = fcmp olt double %10, 0.000000e+00 ; a * g < 0.0
|
|
br i1 %11, label %enforce, label %loop
|
|
|
|
enforce:
|
|
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([48 x i8], [48 x i8]* @"ASSERTION", i32 0, i32 0))
|
|
call void @exit(i32 1) #6
|
|
unreachable
|
|
|
|
loop:
|
|
%13 = load double, double* %4, align 8 ; load a
|
|
%14 = load double, double* %3, align 8 ; load g
|
|
%15 = fsub double %13, %14 ; a - g
|
|
%16 = call double @llvm.fabs.f64(double %15) ; fabs(a - g)
|
|
%17 = load double, double* %5, align 8 ; load iota
|
|
%18 = fcmp ogt double %16, %17 ; fabs(a - g) > iota
|
|
br i1 %18, label %loop_body, label %eom
|
|
|
|
loop_body:
|
|
%19 = load double, double* %4, align 8 ; load a
|
|
%20 = load double, double* %3, align 8 ; load g
|
|
%21 = fadd double %19, %20 ; a + g
|
|
%22 = fdiv double %21, 2.000000e+00 ; (a + g) / 2.0
|
|
store double %22, double* %6, align 8 ; store %22 in a1
|
|
|
|
%23 = load double, double* %4, align 8 ; load a
|
|
%24 = load double, double* %3, align 8 ; load g
|
|
%25 = fmul double %23, %24 ; a * g
|
|
%26 = call double @sqrt(double %25) #4 ; sqrt(a * g)
|
|
store double %26, double* %7, align 8 ; store %26 in g1
|
|
|
|
%27 = load double, double* %6, align 8 ; load a1
|
|
store double %27, double* %4, align 8 ; store a1 in a
|
|
|
|
%28 = load double, double* %7, align 8 ; load g1
|
|
store double %28, double* %3, align 8 ; store g1 in g
|
|
|
|
br label %loop
|
|
|
|
eom:
|
|
%29 = load double, double* %4, align 8 ; load a
|
|
ret double %29 ; return a
|
|
}
|
|
|
|
;----------------------------------------------------------------
|
|
;-- main
|
|
define i32 @main() #0 {
|
|
%1 = alloca double, align 8 ; allocate x
|
|
%2 = alloca double, align 8 ; allocate y
|
|
|
|
store double 1.000000e+00, double* %1, align 8 ; store 1.0 in x
|
|
|
|
%3 = call double @sqrt(double 2.000000e+00) #4 ; calculate the square root of two
|
|
%4 = fdiv double 1.000000e+00, %3 ; divide 1.0 by %3
|
|
store double %4, double* %2, align 8 ; store %4 in y
|
|
|
|
%5 = load double, double* %2, align 8 ; reload y
|
|
%6 = load double, double* %1, align 8 ; reload x
|
|
%7 = call double @agm(double %6, double %5) ; agm(x, y)
|
|
|
|
%8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([42 x i8], [42 x i8]* @"OUTPUT", i32 0, i32 0), double %7)
|
|
|
|
ret i32 0 ; finished
|
|
}
|
|
|
|
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
|
|
attributes #1 = { noreturn "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="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" }
|
|
attributes #2 = { nounwind readnone speculatable }
|
|
attributes #4 = { nounwind }
|
|
attributes #6 = { noreturn }
|