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' 37target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 38target triple = "x86_64-unknown-linux-gnu" 39 40%struct.FVector = type { float, float, float } 41 42define zeroext i1 @foo(x86_fp80 %x, x86_fp80 %y) noinline optnone { 43entry: 44 %x.addr = alloca x86_fp80, align 16 45 %y.addr = alloca x86_fp80, align 16 46 store x86_fp80 %x, ptr %x.addr, align 16 47 store x86_fp80 %y, ptr %y.addr, align 16 48 %0 = load x86_fp80, ptr %x.addr, align 16 49 %1 = load x86_fp80, ptr %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 66lor.rhs: ; preds = %entry 67 %2 = load x86_fp80, ptr %x.addr, align 16 68 %call = call zeroext i1 @bar(x86_fp80 %2) 69 br label %lor.end 70 71lor.end: ; preds = %lor.rhs, %entry 72 %3 = phi i1 [ true, %entry ], [ %call, %lor.rhs ] 73 ret i1 %3 74} 75 76declare zeroext i1 @bar(x86_fp80) 77 78define i32 @main() noinline optnone { 79entry: 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, ptr %retval, align 4 85 call void @llvm.lifetime.start.p0(i64 12, ptr %v) nounwind 86 store float 1.000000e+00, ptr %v, align 4 87 %y.i = getelementptr inbounds %struct.FVector, ptr %v, i64 0, i32 1 88 store float 1.000000e+00, ptr %y.i, align 4 89 %z.i = getelementptr inbounds %struct.FVector, ptr %v, i64 0, i32 2 90 store float 1.000000e+00, ptr %z.i, align 4 91 %0 = load float, ptr %v, align 4 92 %cmp.i = fcmp oeq float %0, 1.000000e+00 93 br i1 %cmp.i, label %if.then.i, label %if.else.i 94 95if.then.i: ; preds = %entry 96 %retval.sroa.0.0.copyload.i = load <2 x float>, ptr %v, align 4 97 %retval.sroa.6.0..sroa_idx16.i = getelementptr inbounds %struct.FVector, ptr %v, i64 0, i32 2 98 %retval.sroa.6.0.copyload.i = load float, ptr %retval.sroa.6.0..sroa_idx16.i, align 4 99 br label %func.exit 100 101if.else.i: ; preds = %entry 102 103; Test 2 104; In order to feed the first PHI node in func.exit handlePHINodesInSuccessorBlocks() 105; generates a local value instruction, but it cannot handle the second PHI node and 106; returns false to let SelectionDAGISel handle both cases. Make sure the generated 107; local value instruction is removed. 108; CHECK-LABEL: main: 109; CHECK-LABEL: .LBB1_2: 110; CHECK: xorps [[REG:%xmm[0-7]]], [[REG]] 111; CHECK-NOT: xorps [[REG]], [[REG]] 112; CHECK-LABEL: .LBB1_3: 113 114 %cmp3.i = fcmp olt float %0, 0x3E45798EE0000000 115 br i1 %cmp3.i, label %func.exit, label %if.end.5.i 116 117if.end.5.i: ; preds = %if.else.i 118 %retval.sroa.0.0.vec.insert13.i = insertelement <2 x float> undef, float %0, i32 0 119 %retval.sroa.0.4.vec.insert15.i = insertelement <2 x float> %retval.sroa.0.0.vec.insert13.i, float %0, i32 1 120 br label %func.exit 121 122func.exit: ; preds = %if.then.i, %if.else.i, %if.end.5.i 123 %retval.sroa.6.0.i = phi float [ %retval.sroa.6.0.copyload.i, %if.then.i ], [ %0, %if.end.5.i ], [ 0.000000e+00, %if.else.i ] 124 %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 ] 125 %.fca.0.insert.i = insertvalue { <2 x float>, float } undef, <2 x float> %retval.sroa.0.0.i, 0 126 %.fca.1.insert.i = insertvalue { <2 x float>, float } %.fca.0.insert.i, float %retval.sroa.6.0.i, 1 127 store { <2 x float>, float } %.fca.1.insert.i, ptr %tmp, align 8 128 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %ref.tmp, ptr align 4 %tmp, i64 12, i1 false) 129 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %v, ptr align 4 %ref.tmp, i64 12, i1 false) 130 call void @llvm.lifetime.end.p0(i64 12, ptr %v) nounwind 131 ret i32 0 132} 133 134declare void @llvm.lifetime.start.p0(i64, ptr nocapture) argmemonly nounwind 135 136declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1) argmemonly nounwind 137 138declare void @llvm.lifetime.end.p0(i64, ptr nocapture) argmemonly nounwind 139