Home | History | Annotate | Download | only in ValueTracking
      1 ; RUN: opt -S -licm < %s | FileCheck %s
      2 
      3 ; Note: the !invariant.load is there just solely to let us call @use()
      4 ; to add a fake use, and still have the aliasing work out.  The call
      5 ; to @use(0) is just to provide a may-unwind exit out of the loop, so
      6 ; that LICM cannot hoist out the load simply because it is guaranteed
      7 ; to execute.
      8 
      9 declare void @use(i32)
     10 
     11 define void @f_0(i8* align 4 dereferenceable(1024) %ptr) {
     12 ; CHECK-LABEL: @f_0(
     13 ; CHECK: entry:
     14 ; CHECK:  %val = load i32, i32* %ptr.i32
     15 ; CHECK:  br label %loop
     16 ; CHECK: loop:
     17 ; CHECK:  call void @use(i32 0)
     18 ; CHECK-NEXT:  call void @use(i32 %val)
     19 
     20 
     21 entry:
     22   %ptr.gep = getelementptr i8, i8* %ptr, i32 32
     23   %ptr.i32 = bitcast i8* %ptr.gep to i32*
     24   br label %loop
     25 
     26 loop:
     27   call void @use(i32 0)
     28   %val = load i32, i32* %ptr.i32, !invariant.load !{}
     29   call void @use(i32 %val)
     30   br label %loop
     31 }
     32 
     33 define void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) {
     34 ; CHECK-LABEL: @f_1(
     35 entry:
     36   %ptr.gep = getelementptr i8, i8* %ptr, i32 32
     37   %ptr.i32 = bitcast i8* %ptr.gep to i32*
     38   %ptr_is_null = icmp eq i8* %ptr, null
     39   br i1 %ptr_is_null, label %leave, label %loop
     40 
     41 ; CHECK: loop.preheader:
     42 ; CHECK:   %val = load i32, i32* %ptr.i32
     43 ; CHECK:   br label %loop
     44 ; CHECK: loop:
     45 ; CHECK:  call void @use(i32 0)
     46 ; CHECK-NEXT:  call void @use(i32 %val)
     47 
     48 loop:
     49   call void @use(i32 0)
     50   %val = load i32, i32* %ptr.i32, !invariant.load !{}
     51   call void @use(i32 %val)
     52   br label %loop
     53 
     54 leave:
     55   ret void
     56 }
     57 
     58 define void @f_2(i8* align 4 dereferenceable_or_null(1024) %ptr) {
     59 ; CHECK-LABEL: @f_2(
     60 ; CHECK-NOT: load
     61 ; CHECK:  call void @use(i32 0)
     62 ; CHECK-NEXT:  %val = load i32, i32* %ptr.i32, !invariant.load !0
     63 ; CHECK-NEXT:  call void @use(i32 %val)
     64 
     65 entry:
     66   ;; Can't hoist, since the alignment does not work out -- (<4 byte
     67   ;; aligned> + 30) is not necessarily 4 byte aligned.
     68 
     69   %ptr.gep = getelementptr i8, i8* %ptr, i32 30
     70   %ptr.i32 = bitcast i8* %ptr.gep to i32*
     71   %ptr_is_null = icmp eq i8* %ptr, null
     72   br i1 %ptr_is_null, label %leave, label %loop
     73 
     74 loop:
     75   call void @use(i32 0)
     76   %val = load i32, i32* %ptr.i32, !invariant.load !{}
     77   call void @use(i32 %val)
     78   br label %loop
     79 
     80 leave:
     81   ret void
     82 }
     83