Hi all, I'm looking at following code snippet: void t2(double *x) { long long a[2]; a[0] = 3; a[1] = 5; *x = * ((double *) a); *(x+1) = * ((double *) &a[a[0]-2]); } I use generate LLVM code using my own front-end that looks like: ; ModuleID = 'jb.c' target datalayout "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i386-pc-linux-gnu" define void @t2(double* %x) { L.entry: %a = alloca [2 x i64], align 4 %x.addr = alloca double* store double* %x, double** %x.addr %0 = bitcast [2 x i64]* %a to i64* store i64 3, i64* %0 %1 = getelementptr [2 x i64]* %a, i32 0, i32 1 store i64 5, i64* %1 %2 = bitcast [2 x i64]* %a to double* %3 = load double* %2 %4 = load double** %x.addr store double %3, double* %4 %5 = bitcast [2 x i64]* %a to double* %6 = bitcast double* %5 to i8* %7 = bitcast [2 x i64]* %a to i64* %8 = load i64* %7 %9 = sub i64 %8, 2 %10 = trunc i64 %9 to i32 %11 = mul i32 %10, 8 %12 = getelementptr i8* %6, i32 %11 %13 = bitcast i8* %12 to double* %14 = load double* %13 %15 = load double** %x.addr %16 = bitcast double* %15 to i8* %17 = getelementptr i8* %16, i32 8 %18 = bitcast i8* %17 to double* store double %14, double* %18 ret void } when I use LLVM opt on this .ll file I've got: ; ModuleID = 'jb.ll' target datalayout "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i386-pc-linux-gnu" define void @t2(double* nocapture %x) nounwind { L.entry: store double 1.482197e-323, double* %x, align 4 ret void } Now if I use clang -O2 I've got following llvm file: ; ModuleID = 'jb.clang.ll' target datalayout "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i386-unknown-linux-gnu" define void @t2(double* nocapture %x) nounwind { store double 1.482197e-323, double* %x, align 4, !tbaa !0 %1 = getelementptr inbounds double* %x, i32 1 store double 2.470328e-323, double* %1, align 4, !tbaa !0 ret void } !0 = metadata !{metadata !"double", metadata !1} !1 = metadata !{metadata !"omnipotent char", metadata !2} !2 = metadata !{metadata !"Simple C/C++ TBAA", null} Which is what I was expecting, to me it seems that there is a bug in LLVM opt, is it the case ? Thanks for your answer Best Regards Seb -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120228/f4e73059/attachment.html>
Hi Seb, I think it is an opt bug. If you run opt at -O1 then you get: define void @t2(double* nocapture %x) nounwind { L.entry: %a = alloca [2 x i64], align 8 %0 = getelementptr inbounds [2 x i64]* %a, i32 0, i32 0 store i64 3, i64* %0, align 8 %1 = getelementptr [2 x i64]* %a, i32 0, i32 1 store i64 5, i64* %1, align 8 %2 = bitcast [2 x i64]* %a to double* %3 = load double* %2, align 8 store double %3, double* %x, align 4 %4 = load i64* %0, align 8 %5 = add i64 %4, 536870910 %6 = trunc i64 %5 to i32 %7 = getelementptr [2 x i64]* %a, i32 0, i32 %6 %8 = bitcast i64* %7 to double* %9 = load double* %8, align 8 %10 = getelementptr double* %x, i32 1 store double %9, double* %10, align 4 ret void } Notice "%5 = add i64 %4, 536870910". This is presumably trying to subtract 2, but this doesn't seem to be the same as subtracting 2 even after the truncate to 32 bits. This then causes a load from a wild stack location later. Probably at a higher optimization level this is recognized as an undefined operation causing code after it to be removed, including the final store. Ciao, Duncan. On 28/02/12 14:58, Seb wrote:> Hi all, > > I'm looking at following code snippet: > > void t2(double *x) > { > long long a[2]; > a[0] = 3; > a[1] = 5; > *x = * ((double *) a); > *(x+1) = * ((double *) &a[a[0]-2]); > } > > I use generate LLVM code using my own front-end that looks like: > > > ; ModuleID = 'jb.c' > target datalayout > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > target triple = "i386-pc-linux-gnu" > define void @t2(double* %x) { > L.entry: > %a = alloca [2 x i64], align 4 > > %x.addr = alloca double* > store double* %x, double** %x.addr > %0 = bitcast [2 x i64]* %a to i64* > store i64 3, i64* %0 > %1 = getelementptr [2 x i64]* %a, i32 0, i32 1 > store i64 5, i64* %1 > %2 = bitcast [2 x i64]* %a to double* > %3 = load double* %2 > %4 = load double** %x.addr > store double %3, double* %4 > %5 = bitcast [2 x i64]* %a to double* > %6 = bitcast double* %5 to i8* > %7 = bitcast [2 x i64]* %a to i64* > %8 = load i64* %7 > %9 = sub i64 %8, 2 > %10 = trunc i64 %9 to i32 > %11 = mul i32 %10, 8 > %12 = getelementptr i8* %6, i32 %11 > %13 = bitcast i8* %12 to double* > %14 = load double* %13 > %15 = load double** %x.addr > %16 = bitcast double* %15 to i8* > %17 = getelementptr i8* %16, i32 8 > %18 = bitcast i8* %17 to double* > store double %14, double* %18 > ret void > } > > when I use LLVM opt on this .ll file I've got: > > ; ModuleID = 'jb.ll' > target datalayout > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > target triple = "i386-pc-linux-gnu" > > define void @t2(double* nocapture %x) nounwind { > L.entry: > store double 1.482197e-323, double* %x, align 4 > ret void > } > > Now if I use clang -O2 I've got following llvm file: > > ; ModuleID = 'jb.clang.ll' > target datalayout > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > target triple = "i386-unknown-linux-gnu" > > define void @t2(double* nocapture %x) nounwind { > store double 1.482197e-323, double* %x, align 4, !tbaa !0 > %1 = getelementptr inbounds double* %x, i32 1 > store double 2.470328e-323, double* %1, align 4, !tbaa !0 > ret void > } > > !0 = metadata !{metadata !"double", metadata !1} > !1 = metadata !{metadata !"omnipotent char", metadata !2} > !2 = metadata !{metadata !"Simple C/C++ TBAA", null} > > Which is what I was expecting, to me it seems that there is a bug in LLVM opt, > is it the case ? > > Thanks for your answer > Best Regards > Seb > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Hi Duncan, Indeed, I made same experiment as you and concluded that it might be a BUG. Shall I submit it to llvm bug tracking support ? Do you think there could be a work-around ? Thanks for your quick answer. Best Regards Seb 2012/2/28 Duncan Sands <baldrick at free.fr>> Hi Seb, I think it is an opt bug. If you run opt at -O1 then you get: > > define void @t2(double* nocapture %x) nounwind { > L.entry: > %a = alloca [2 x i64], align 8 > %0 = getelementptr inbounds [2 x i64]* %a, i32 0, i32 0 > store i64 3, i64* %0, align 8 > %1 = getelementptr [2 x i64]* %a, i32 0, i32 1 > store i64 5, i64* %1, align 8 > %2 = bitcast [2 x i64]* %a to double* > %3 = load double* %2, align 8 > store double %3, double* %x, align 4 > %4 = load i64* %0, align 8 > %5 = add i64 %4, 536870910 > %6 = trunc i64 %5 to i32 > %7 = getelementptr [2 x i64]* %a, i32 0, i32 %6 > %8 = bitcast i64* %7 to double* > %9 = load double* %8, align 8 > %10 = getelementptr double* %x, i32 1 > store double %9, double* %10, align 4 > ret void > } > > Notice "%5 = add i64 %4, 536870910". This is presumably trying to > subtract 2, > but this doesn't seem to be the same as subtracting 2 even after the > truncate > to 32 bits. > > This then causes a load from a wild stack location later. Probably at a > higher > optimization level this is recognized as an undefined operation causing > code > after it to be removed, including the final store. > > Ciao, Duncan. > > > On 28/02/12 14:58, Seb wrote: > > Hi all, > > > > I'm looking at following code snippet: > > > > void t2(double *x) > > { > > long long a[2]; > > a[0] = 3; > > a[1] = 5; > > *x = * ((double *) a); > > *(x+1) = * ((double *) &a[a[0]-2]); > > } > > > > I use generate LLVM code using my own front-end that looks like: > > > > > > ; ModuleID = 'jb.c' > > target datalayout > > > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > > target triple = "i386-pc-linux-gnu" > > define void @t2(double* %x) { > > L.entry: > > %a = alloca [2 x i64], align 4 > > > > %x.addr = alloca double* > > store double* %x, double** %x.addr > > %0 = bitcast [2 x i64]* %a to i64* > > store i64 3, i64* %0 > > %1 = getelementptr [2 x i64]* %a, i32 0, i32 1 > > store i64 5, i64* %1 > > %2 = bitcast [2 x i64]* %a to double* > > %3 = load double* %2 > > %4 = load double** %x.addr > > store double %3, double* %4 > > %5 = bitcast [2 x i64]* %a to double* > > %6 = bitcast double* %5 to i8* > > %7 = bitcast [2 x i64]* %a to i64* > > %8 = load i64* %7 > > %9 = sub i64 %8, 2 > > %10 = trunc i64 %9 to i32 > > %11 = mul i32 %10, 8 > > %12 = getelementptr i8* %6, i32 %11 > > %13 = bitcast i8* %12 to double* > > %14 = load double* %13 > > %15 = load double** %x.addr > > %16 = bitcast double* %15 to i8* > > %17 = getelementptr i8* %16, i32 8 > > %18 = bitcast i8* %17 to double* > > store double %14, double* %18 > > ret void > > } > > > > when I use LLVM opt on this .ll file I've got: > > > > ; ModuleID = 'jb.ll' > > target datalayout > > > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > > target triple = "i386-pc-linux-gnu" > > > > define void @t2(double* nocapture %x) nounwind { > > L.entry: > > store double 1.482197e-323, double* %x, align 4 > > ret void > > } > > > > Now if I use clang -O2 I've got following llvm file: > > > > ; ModuleID = 'jb.clang.ll' > > target datalayout > > > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" > > target triple = "i386-unknown-linux-gnu" > > > > define void @t2(double* nocapture %x) nounwind { > > store double 1.482197e-323, double* %x, align 4, !tbaa !0 > > %1 = getelementptr inbounds double* %x, i32 1 > > store double 2.470328e-323, double* %1, align 4, !tbaa !0 > > ret void > > } > > > > !0 = metadata !{metadata !"double", metadata !1} > > !1 = metadata !{metadata !"omnipotent char", metadata !2} > > !2 = metadata !{metadata !"Simple C/C++ TBAA", null} > > > > Which is what I was expecting, to me it seems that there is a bug in > LLVM opt, > > is it the case ? > > > > Thanks for your answer > > Best Regards > > Seb > > > > > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120228/0e73a19f/attachment.html>
> void t2(double *x) > { > long long a[2]; > a[0] = 3; > a[1] = 5; > *x = * ((double *) a); > *(x+1) = * ((double *) &a[a[0]-2]); > }Doesn't this code violate the strict aliasing rules? John
On 28/02/12 17:48, John Regehr wrote:>> void t2(double *x) >> { >> long long a[2]; >> a[0] = 3; >> a[1] = 5; >> *x = * ((double *) a); >> *(x+1) = * ((double *) &a[a[0]-2]); >> } > > Doesn't this code violate the strict aliasing rules?Maybe, but the LLVM IR he showed seems perfectly well defined. Ciao, Duncan.