[llvm-dev] varargs, the x86, and clang
Preston Briggs via llvm-dev
llvm-dev at lists.llvm.org
Mon Sep 28 16:07:42 PDT 2015
When I use clang on an x86-64 to spit out the LLVM, like this
clang -O -S -emit-llvm varargstest.c
where varargstest.c looks like this
int add_em_up(int count, ...) {
va_list ap;
int i, sum;
va_start(ap, count);
sum = 0;
for (i = 0; i < count; i++)
sum += va_arg(ap, int);
va_end(ap);
return sum;
}
I see LLVM that looks like it's been customized for the x86-64,
versus the varargs stuff I was led to expect from the LLVM IR documentation.
define i32 @add_em_up(i32 %count, ...) #0 {
entry:
%ap = alloca [1 x %struct.__va_list_tag], align 16
%arraydecay1 = bitcast [1 x %struct.__va_list_tag]* %ap to i8*
call void @llvm.va_start(i8* %arraydecay1)
%cmp7 = icmp sgt i32 %count, 0
br i1 %cmp7, label %for.body.lr.ph, label %for.end
for.body.lr.ph: ; preds = %entry
%gp_offset_p = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap,
i64 0, i64 0, i32 0
%0 = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i64 0, i64
0, i32 3
%overflow_arg_area_p = getelementptr inbounds [1 x
%struct.__va_list_tag]* %ap, i64 0, i64 0, i32 2
%gp_offset.pre = load i32* %gp_offset_p, align 16
br label %for.body
for.body: ; preds = %vaarg.end, %
for.body.lr.ph
%gp_offset = phi i32 [ %gp_offset.pre, %for.body.lr.ph ], [ %gp_offset10,
%vaarg.end ]
%sum.09 = phi i32 [ 0, %for.body.lr.ph ], [ %add, %vaarg.end ]
%i.08 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %vaarg.end ]
%fits_in_gp = icmp ult i32 %gp_offset, 41
br i1 %fits_in_gp, label %vaarg.in_reg, label %vaarg.in_mem
vaarg.in_reg: ; preds = %for.body
%reg_save_area = load i8** %0, align 16
%1 = sext i32 %gp_offset to i64
%2 = getelementptr i8* %reg_save_area, i64 %1
%3 = add i32 %gp_offset, 8
store i32 %3, i32* %gp_offset_p, align 16
br label %vaarg.end
vaarg.in_mem: ; preds = %for.body
%overflow_arg_area = load i8** %overflow_arg_area_p, align 8
%overflow_arg_area.next = getelementptr i8* %overflow_arg_area, i64 8
store i8* %overflow_arg_area.next, i8** %overflow_arg_area_p, align 8
br label %vaarg.end
vaarg.end: ; preds = %vaarg.in_mem,
%vaarg.in_reg
%gp_offset10 = phi i32 [ %3, %vaarg.in_reg ], [ %gp_offset, %vaarg.in_mem
]
%vaarg.addr.in = phi i8* [ %2, %vaarg.in_reg ], [ %overflow_arg_area,
%vaarg.in_mem ]
%vaarg.addr = bitcast i8* %vaarg.addr.in to i32*
%4 = load i32* %vaarg.addr, align 4
%add = add nsw i32 %4, %sum.09
%inc = add nsw i32 %i.08, 1
%exitcond = icmp eq i32 %inc, %count
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %vaarg.end,
%entry
%sum.0.lcssa = phi i32 [ 0, %entry ], [ %add, %vaarg.end ]
call void @llvm.va_end(i8* %arraydecay1)
ret i32 %sum.0.lcssa
}
Notice at the bottom of the block labeled "for.body" that there's a test
that determines
whether to look for an argument on the stack or in a register. I see
something similar w/ or w/o the -O flag.
This isn't what I was led to expect by the LLVM IR documentation.
Is there a way to avoid this "premature" optimization?
I tried things like -arch mips and -march=mips but get complaints
about unrecognized flags (-arch) or unknown target architecture CPU 'mips'.
Why's that? The man page suggests both should work.
Thanks,
Preston
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150928/fd6d3b15/attachment.html>
More information about the llvm-dev
mailing list