brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 9d97d89 Raw
326 lines · c
1// RUN: %clang_cc1 -Wno-return-type -Wno-unused-value -emit-llvm %s -w -o - | FileCheck %s2 3// CHECK: @i = {{(dso_local )?}}global [[INT:i[0-9]+]] 04volatile int i, j, k;5volatile int ar[5];6volatile char c;7// CHECK: @ci = {{(dso_local )?}}global [[CINT:.*]] zeroinitializer8volatile _Complex int ci;9volatile struct S {10#ifdef __cplusplus11  void operator =(volatile struct S&o) volatile;12#endif13  int i;14} a, b;15 16//void operator =(volatile struct S&o1, volatile struct S&o2) volatile;17int printf(const char *, ...);18 19 20// Note that these test results are very much specific to C!21// Assignments in C++ yield l-values, not r-values, and the situations22// that do implicit lvalue-to-rvalue conversion are substantially23// reduced.24 25// CHECK-LABEL: define {{.*}}void @test()26void test(void) {27  // CHECK: load volatile [[INT]], ptr @i28  i;29  // CHECK-NEXT: load volatile [[INT]], ptr @ci, align [[ALIGN:[0-9]+]]30  // CHECK-NEXT: load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP:[0-9]+]]31  // CHECK-NEXT: sitofp [[INT]]32  (float)(ci);33  // CHECK-NEXT: load volatile [[INT]], ptr @ci, align [[ALIGN]]34  // CHECK-NEXT: load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]35  (void)ci;36  // CHECK-NEXT: memcpy37  (void)a;38  // CHECK-NEXT: [[R:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]39  // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]40  // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci, align [[ALIGN]]41  // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]42  (void)(ci=ci);43  // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr @j44  // CHECK-NEXT: store volatile [[INT]] [[T]], ptr @i45  (void)(i=j);46  // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]47  // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]48  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]49  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]50  // Not sure why they're ordered this way.51  // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]52  // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]53  // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci, align [[ALIGN]]54  // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]55  ci+=ci;56 57  // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]58  // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]59  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]60  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]61  // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]62  // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]63  // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci, align [[ALIGN]]64  // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]65  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci, align [[ALIGN]]66  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1), align [[ALIGN_GEP]]67  // These additions can be elided68  // CHECK-NEXT: add [[INT]] [[R]], [[R2]]69  // CHECK-NEXT: add [[INT]] [[I]], [[I2]]70  (ci += ci) + ci;71  // CHECK-NEXT: call void asm72  asm("nop");73  // CHECK-NEXT: load volatile74  // CHECK-NEXT: load volatile75  // CHECK-NEXT: add nsw [[INT]]76  // CHECK-NEXT: store volatile77  // CHECK-NEXT: load volatile78  // CHECK-NEXT: add nsw [[INT]]79  (i += j) + k;80  // CHECK-NEXT: call void asm81  asm("nop");82  // CHECK-NEXT: load volatile83  // CHECK-NEXT: load volatile84  // CHECK-NEXT: add nsw [[INT]]85  // CHECK-NEXT: store volatile86  // CHECK-NEXT: add nsw [[INT]]87  (i += j) + 1;88  // CHECK-NEXT: call void asm89  asm("nop");90  // CHECK-NEXT: load volatile91  // CHECK-NEXT: load volatile92  // CHECK-NEXT: load volatile93  // CHECK-NEXT: load volatile94  // CHECK-NEXT: add [[INT]]95  // CHECK-NEXT: add [[INT]]96  ci+ci;97 98  // CHECK-NEXT: load volatile99  __real i;100  // CHECK-NEXT: load volatile101  // CHECK-NEXT: load volatile102  +ci;103  // CHECK-NEXT: call void asm104  asm("nop");105  // CHECK-NEXT: load volatile106  // CHECK-NEXT: store volatile107  (void)(i=i);108  // CHECK-NEXT: load volatile109  // CHECK-NEXT: store volatile110  // CHECK-NEXT: sitofp111  (float)(i=i);112  // CHECK-NEXT: load volatile113  (void)i;114  // CHECK-NEXT: load volatile115  // CHECK-NEXT: store volatile116  i=i;117  // CHECK-NEXT: load volatile118  // CHECK-NEXT: store volatile119  // CHECK-NEXT: store volatile120  i=i=i;121#ifndef __cplusplus122  // CHECK-NEXT: load volatile123  // CHECK-NEXT: store volatile124  (void)__builtin_choose_expr(0, i=i, j=j);125#endif126  // CHECK-NEXT: load volatile127  // CHECK-NEXT: icmp128  // CHECK-NEXT: br i1129  // CHECK: load volatile130  // CHECK-NEXT: store volatile131  // CHECK-NEXT: br label132  // CHECK: load volatile133  // CHECK-NEXT: store volatile134  // CHECK-NEXT: br label135  k ? (i=i) : (j=j);136  // CHECK: phi137  // CHECK-NEXT: load volatile138  // CHECK-NEXT: load volatile139  // CHECK-NEXT: store volatile140  (void)(i,(i=i));141  // CHECK-NEXT: load volatile142  // CHECK-NEXT: store volatile143  // CHECK-NEXT: load volatile144  i=i,i;145  // CHECK-NEXT: load volatile146  // CHECK-NEXT: store volatile147  // CHECK-NEXT: load volatile148  // CHECK-NEXT: store volatile149  (i=j,k=j);150  // CHECK-NEXT: load volatile151  // CHECK-NEXT: store volatile152  // CHECK-NEXT: load volatile153  (i=j,k);154  // CHECK-NEXT: load volatile155  // CHECK-NEXT: load volatile156  (i,j);157  // CHECK-NEXT: load volatile158  // CHECK-NEXT: trunc159  // CHECK-NEXT: store volatile160  // CHECK-NEXT: sext161  // CHECK-NEXT: store volatile162  i=c=k;163  // CHECK-NEXT: load volatile164  // CHECK-NEXT: load volatile165  // CHECK-NEXT: add nsw [[INT]]166  // CHECK-NEXT: store volatile167  i+=k;168  // CHECK-NEXT: load volatile169  // CHECK-NEXT: load volatile170  ci;171#ifndef __cplusplus172  // CHECK-NEXT: load volatile173  // CHECK-NEXT: load volatile174  (int)ci;175  // CHECK-NEXT: load volatile176  // CHECK-NEXT: load volatile177  // CHECK-NEXT: icmp ne178  // CHECK-NEXT: icmp ne179  // CHECK-NEXT: or i1180  (_Bool)ci;181#endif182  // CHECK-NEXT: load volatile183  // CHECK-NEXT: load volatile184  // CHECK-NEXT: store volatile185  // CHECK-NEXT: store volatile186  ci=ci;187  // CHECK-NEXT: load volatile188  // CHECK-NEXT: load volatile189  // CHECK-NEXT: store volatile190  // CHECK-NEXT: store volatile191  // CHECK-NEXT: store volatile192  // CHECK-NEXT: store volatile193  ci=ci=ci;194  // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1)195  // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1)196  // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1)197  __imag ci = __imag ci = __imag ci;198  // CHECK-NEXT: load volatile199  // CHECK-NEXT: store volatile200  __real (i = j);201  // CHECK-NEXT: load volatile202  __imag i;203  204  // ============================================================205  // FIXME: Test cases we get wrong.206 207  // A use.  We load all of a into a copy of a, then load i.  gcc forgets to do208  // the assignment.209  // (a = a).i;210 211  // ============================================================212  // Test cases where we intentionally differ from gcc, due to suspected bugs in213  // gcc.214 215  // Not a use.  gcc forgets to do the assignment.216  // CHECK-NEXT: call void @llvm.memcpy{{.*}}, i1 true217  // CHECK-NEXT: call void @llvm.memcpy{{.*}}, i1 true218  ((a=a),a);219 220  // Not a use.  gcc gets this wrong, it doesn't emit the copy!  221  // (void)(a=a);222 223  // Not a use.  gcc got this wrong in 4.2 and omitted the side effects224  // entirely, but it is fixed in 4.4.0.225  // CHECK-NEXT: load volatile226  // CHECK-NEXT: store volatile227  __imag (i = j);228 229#ifndef __cplusplus230  // A use of the real part231  // CHECK-NEXT: load volatile232  // CHECK-NEXT: load volatile233  // CHECK-NEXT: store volatile234  // CHECK-NEXT: store volatile235  // CHECK-NEXT: sitofp236  (float)(ci=ci);237  // Not a use, bug?  gcc treats this as not a use, that's probably a bug due to238  // tree folding ignoring volatile.239  // CHECK-NEXT: load volatile240  // CHECK-NEXT: load volatile241  // CHECK-NEXT: store volatile242  // CHECK-NEXT: store volatile243  (int)(ci=ci);244#endif245 246  // A use.247  // CHECK-NEXT: load volatile248  // CHECK-NEXT: store volatile249  // CHECK-NEXT: sitofp250  (float)(i=i);251  // A use.  gcc treats this as not a use, that's probably a bug due to tree252  // folding ignoring volatile.253  // CHECK-NEXT: load volatile254  // CHECK-NEXT: store volatile255  (int)(i=i);256 257  // A use.258  // CHECK-NEXT: load volatile259  // CHECK-NEXT: store volatile260  // CHECK-NEXT: sub261  -(i=j);262  // A use.  gcc treats this a not a use, that's probably a bug due to tree263  // folding ignoring volatile.264  // CHECK-NEXT: load volatile265  // CHECK-NEXT: store volatile266  +(i=k);267 268  // A use. gcc treats this a not a use, that's probably a bug due to tree269  // folding ignoring volatile.270  // CHECK-NEXT: load volatile271  // CHECK-NEXT: load volatile272  // CHECK-NEXT: store volatile273  // CHECK-NEXT: store volatile274  __real (ci=ci);275 276  // A use.277  // CHECK-NEXT: load volatile278  // CHECK-NEXT: add279  i + 0;280  // A use.281  // CHECK-NEXT: load volatile282  // CHECK-NEXT: store volatile283  // CHECK-NEXT: load volatile284  // CHECK-NEXT: add285  (i=j) + i;286  // A use.  gcc treats this as not a use, that's probably a bug due to tree287  // folding ignoring volatile.288  // CHECK-NEXT: load volatile289  // CHECK-NEXT: store volatile290  // CHECK-NEXT: add291  (i=j) + 0;292 293#ifdef __cplusplus294  (i,j)=k;295  (j=k,i)=i;296  struct { int x; } s, s1;297  printf("s is at %p\n", &s);298  printf("s is at %p\n", &(s = s1));299  printf("s.x is at %p\n", &((s = s1).x));300#endif301}302 303extern volatile enum X x;304// CHECK-LABEL: define {{.*}}void @test1()305void test1(void) {306  extern void test1_helper(void);307  test1_helper();308  // CHECK: call {{.*}}void @test1_helper()309  // CHECK-NEXT: ret void310  x;311  (void) x;312  return x;313}314 315// CHECK: define {{.*}} @test2()316int test2(void) {317  // CHECK: load volatile i32, ptr318  // CHECK-NEXT: load volatile i32, ptr319  // CHECK-NEXT: load volatile i32, ptr320  // CHECK-NEXT: add i32321  // CHECK-NEXT: add i32322  // CHECK-NEXT: store volatile i32323  // CHECK-NEXT: ret i32324  return i += ci;325}326