Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s | FileCheck %s
      2 ;
      3 ; Generated with clang -O2 -S -emit-llvm
      4 ;
      5 ; /* Test 1 */
      6 ; extern "C" bool bar (long double);
      7 ; __attribute__((optnone))
      8 ; extern "C" bool foo(long double x, long double y)
      9 ; {
     10 ;   return (x == y) || (bar(x));
     11 ; }
     12 ;
     13 ; /* Test 2 */
     14 ; struct FVector {
     15 ;   float x, y, z;
     16 ;   inline __attribute__((always_inline)) FVector(float f): x(f), y(f), z(f) {}
     17 ;   inline __attribute__((always_inline)) FVector func(float p) const
     18 ;   {
     19 ;     if( x == 1.f ) {
     20 ;       return *this;
     21 ;     } else if( x < p ) {
     22 ;       return FVector(0.f);
     23 ;     }
     24 ;     return FVector(x);
     25 ;   }
     26 ; };
     27 ; 
     28 ; __attribute__((optnone))
     29 ; int main()
     30 ; {
     31 ;   FVector v(1.0);
     32 ;   v = v.func(1.e-8);
     33 ;   return 0;
     34 ; }
     35 ;
     36 ; ModuleID = 'test.cpp'
     37 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
     38 target triple = "x86_64-unknown-linux-gnu"
     39 
     40 %struct.FVector = type { float, float, float }
     41 
     42 define zeroext i1 @foo(x86_fp80 %x, x86_fp80 %y) noinline optnone {
     43 entry:
     44   %x.addr = alloca x86_fp80, align 16
     45   %y.addr = alloca x86_fp80, align 16
     46   store x86_fp80 %x, x86_fp80* %x.addr, align 16
     47   store x86_fp80 %y, x86_fp80* %y.addr, align 16
     48   %0 = load x86_fp80, x86_fp80* %x.addr, align 16
     49   %1 = load x86_fp80, x86_fp80* %y.addr, align 16
     50   %cmp = fcmp oeq x86_fp80 %0, %1
     51 
     52 ; Test 1
     53 ; Make sure that there is no dead code generated
     54 ; from Fast-ISel Phi-node handling. We should only
     55 ; see one movb of the constant 1, feeding the PHI
     56 ; node in lor.end. This covers the code path with
     57 ; handlePHINodesInSuccessorBlocks() returning true.
     58 ;
     59 ; CHECK-LABEL: foo:
     60 ; CHECK: movb $1,
     61 ; CHECK-NOT: movb $1,
     62 ; CHECK-LABEL: .LBB0_1:
     63 
     64   br i1 %cmp, label %lor.end, label %lor.rhs
     65 
     66 lor.rhs:                                          ; preds = %entry
     67   %2 = load x86_fp80, x86_fp80* %x.addr, align 16
     68   %call = call zeroext i1 @bar(x86_fp80 %2)
     69   br label %lor.end
     70 
     71 lor.end:                                          ; preds = %lor.rhs, %entry
     72   %3 = phi i1 [ true, %entry ], [ %call, %lor.rhs ]
     73   ret i1 %3
     74 }
     75 
     76 declare zeroext i1 @bar(x86_fp80)
     77 
     78 define i32 @main() noinline optnone {
     79 entry:
     80   %retval = alloca i32, align 4
     81   %v = alloca %struct.FVector, align 4
     82   %ref.tmp = alloca %struct.FVector, align 4
     83   %tmp = alloca { <2 x float>, float }, align 8
     84   store i32 0, i32* %retval, align 4
     85   %0 = bitcast %struct.FVector* %v to i8*
     86   call void @llvm.lifetime.start(i64 12, i8* %0) nounwind
     87   %x.i = getelementptr inbounds %struct.FVector, %struct.FVector* %v, i64 0, i32 0
     88   store float 1.000000e+00, float* %x.i, align 4
     89   %y.i = getelementptr inbounds %struct.FVector, %struct.FVector* %v, i64 0, i32 1
     90   store float 1.000000e+00, float* %y.i, align 4
     91   %z.i = getelementptr inbounds %struct.FVector, %struct.FVector* %v, i64 0, i32 2
     92   store float 1.000000e+00, float* %z.i, align 4
     93   %x.i.1 = getelementptr inbounds %struct.FVector, %struct.FVector* %v, i64 0, i32 0
     94   %1 = load float, float* %x.i.1, align 4
     95   %cmp.i = fcmp oeq float %1, 1.000000e+00
     96   br i1 %cmp.i, label %if.then.i, label %if.else.i
     97 
     98 if.then.i:                                        ; preds = %entry
     99   %retval.sroa.0.0..sroa_cast.i = bitcast %struct.FVector* %v to <2 x float>*
    100   %retval.sroa.0.0.copyload.i = load <2 x float>, <2 x float>* %retval.sroa.0.0..sroa_cast.i, align 4
    101   %retval.sroa.6.0..sroa_idx16.i = getelementptr inbounds %struct.FVector, %struct.FVector* %v, i64 0, i32 2
    102   %retval.sroa.6.0.copyload.i = load float, float* %retval.sroa.6.0..sroa_idx16.i, align 4
    103   br label %func.exit
    104 
    105 if.else.i:                                        ; preds = %entry
    106 
    107 ; Test 2
    108 ; In order to feed the first PHI node in func.exit handlePHINodesInSuccessorBlocks()
    109 ; generates a local value instruction, but it cannot handle the second PHI node and
    110 ; returns false to let SelectionDAGISel handle both cases. Make sure the generated 
    111 ; local value instruction is removed.
    112 ; CHECK-LABEL: main:
    113 ; CHECK-LABEL: .LBB1_2:
    114 ; CHECK:       xorps [[REG:%xmm[0-7]]], [[REG]]
    115 ; CHECK-NOT:   xorps [[REG]], [[REG]]
    116 ; CHECK-LABEL: .LBB1_3:
    117 
    118   %cmp3.i = fcmp olt float %1, 0x3E45798EE0000000
    119   br i1 %cmp3.i, label %func.exit, label %if.end.5.i
    120 
    121 if.end.5.i:                                       ; preds = %if.else.i
    122   %retval.sroa.0.0.vec.insert13.i = insertelement <2 x float> undef, float %1, i32 0
    123   %retval.sroa.0.4.vec.insert15.i = insertelement <2 x float> %retval.sroa.0.0.vec.insert13.i, float %1, i32 1
    124   br label %func.exit
    125 
    126 func.exit:                         ; preds = %if.then.i, %if.else.i, %if.end.5.i
    127   %retval.sroa.6.0.i = phi float [ %retval.sroa.6.0.copyload.i, %if.then.i ], [ %1, %if.end.5.i ], [ 0.000000e+00, %if.else.i ]
    128   %retval.sroa.0.0.i = phi <2 x float> [ %retval.sroa.0.0.copyload.i, %if.then.i ], [ %retval.sroa.0.4.vec.insert15.i, %if.end.5.i ], [ zeroinitializer, %if.else.i ]
    129   %.fca.0.insert.i = insertvalue { <2 x float>, float } undef, <2 x float> %retval.sroa.0.0.i, 0
    130   %.fca.1.insert.i = insertvalue { <2 x float>, float } %.fca.0.insert.i, float %retval.sroa.6.0.i, 1
    131   store { <2 x float>, float } %.fca.1.insert.i, { <2 x float>, float }* %tmp, align 8
    132   %2 = bitcast { <2 x float>, float }* %tmp to i8*
    133   %3 = bitcast %struct.FVector* %ref.tmp to i8*
    134   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 12, i32 4, i1 false)
    135   %4 = bitcast %struct.FVector* %v to i8*
    136   %5 = bitcast %struct.FVector* %ref.tmp to i8*
    137   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %4, i8* %5, i64 12, i32 4, i1 false)
    138   %6 = bitcast %struct.FVector* %v to i8*
    139   call void @llvm.lifetime.end(i64 12, i8* %6) nounwind
    140   ret i32 0
    141 }
    142 
    143 declare void @llvm.lifetime.start(i64, i8* nocapture) argmemonly nounwind
    144 
    145 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) argmemonly nounwind
    146 
    147 declare void @llvm.lifetime.end(i64, i8* nocapture) argmemonly nounwind
    148