1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE 3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=CHECK --check-prefix=AVX 4 5; If the target's divss/divps instructions are substantially 6; slower than rcpss/rcpps with a Newton-Raphson refinement, 7; we should generate the estimate sequence. 8 9; See PR21385 ( http://llvm.org/bugs/show_bug.cgi?id=21385 ) 10; for details about the accuracy, speed, and implementation 11; differences of x86 reciprocal estimates. 12 13define float @f32_no_estimate(float %x) #0 { 14; SSE-LABEL: f32_no_estimate: 15; SSE: # BB#0: 16; SSE-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 17; SSE-NEXT: divss %xmm0, %xmm1 18; SSE-NEXT: movaps %xmm1, %xmm0 19; SSE-NEXT: retq 20; 21; AVX-LABEL: f32_no_estimate: 22; AVX: # BB#0: 23; AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero 24; AVX-NEXT: vdivss %xmm0, %xmm1, %xmm0 25; AVX-NEXT: retq 26 %div = fdiv fast float 1.0, %x 27 ret float %div 28} 29 30define float @f32_one_step(float %x) #1 { 31; SSE-LABEL: f32_one_step: 32; SSE: # BB#0: 33; SSE-NEXT: rcpss %xmm0, %xmm2 34; SSE-NEXT: mulss %xmm2, %xmm0 35; SSE-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 36; SSE-NEXT: subss %xmm0, %xmm1 37; SSE-NEXT: mulss %xmm2, %xmm1 38; SSE-NEXT: addss %xmm2, %xmm1 39; SSE-NEXT: movaps %xmm1, %xmm0 40; SSE-NEXT: retq 41; 42; AVX-LABEL: f32_one_step: 43; AVX: # BB#0: 44; AVX-NEXT: vrcpss %xmm0, %xmm0, %xmm1 45; AVX-NEXT: vmulss %xmm1, %xmm0, %xmm0 46; AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero 47; AVX-NEXT: vsubss %xmm0, %xmm2, %xmm0 48; AVX-NEXT: vmulss %xmm0, %xmm1, %xmm0 49; AVX-NEXT: vaddss %xmm0, %xmm1, %xmm0 50; AVX-NEXT: retq 51 %div = fdiv fast float 1.0, %x 52 ret float %div 53} 54 55define float @f32_two_step(float %x) #2 { 56; SSE-LABEL: f32_two_step: 57; SSE: # BB#0: 58; SSE-NEXT: rcpss %xmm0, %xmm2 59; SSE-NEXT: movaps %xmm0, %xmm3 60; SSE-NEXT: mulss %xmm2, %xmm3 61; SSE-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 62; SSE-NEXT: movaps %xmm1, %xmm4 63; SSE-NEXT: subss %xmm3, %xmm4 64; SSE-NEXT: mulss %xmm2, %xmm4 65; SSE-NEXT: addss %xmm2, %xmm4 66; SSE-NEXT: mulss %xmm4, %xmm0 67; SSE-NEXT: subss %xmm0, %xmm1 68; SSE-NEXT: mulss %xmm4, %xmm1 69; SSE-NEXT: addss %xmm4, %xmm1 70; SSE-NEXT: movaps %xmm1, %xmm0 71; SSE-NEXT: retq 72; 73; AVX-LABEL: f32_two_step: 74; AVX: # BB#0: 75; AVX-NEXT: vrcpss %xmm0, %xmm0, %xmm1 76; AVX-NEXT: vmulss %xmm1, %xmm0, %xmm2 77; AVX-NEXT: vmovss {{.*#+}} xmm3 = mem[0],zero,zero,zero 78; AVX-NEXT: vsubss %xmm2, %xmm3, %xmm2 79; AVX-NEXT: vmulss %xmm2, %xmm1, %xmm2 80; AVX-NEXT: vaddss %xmm2, %xmm1, %xmm1 81; AVX-NEXT: vmulss %xmm1, %xmm0, %xmm0 82; AVX-NEXT: vsubss %xmm0, %xmm3, %xmm0 83; AVX-NEXT: vmulss %xmm0, %xmm1, %xmm0 84; AVX-NEXT: vaddss %xmm0, %xmm1, %xmm0 85; AVX-NEXT: retq 86 %div = fdiv fast float 1.0, %x 87 ret float %div 88} 89 90define <4 x float> @v4f32_no_estimate(<4 x float> %x) #0 { 91; SSE-LABEL: v4f32_no_estimate: 92; SSE: # BB#0: 93; SSE-NEXT: movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 94; SSE-NEXT: divps %xmm0, %xmm1 95; SSE-NEXT: movaps %xmm1, %xmm0 96; SSE-NEXT: retq 97; 98; AVX-LABEL: v4f32_no_estimate: 99; AVX: # BB#0: 100; AVX-NEXT: vmovaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 101; AVX-NEXT: vdivps %xmm0, %xmm1, %xmm0 102; AVX-NEXT: retq 103 %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x 104 ret <4 x float> %div 105} 106 107define <4 x float> @v4f32_one_step(<4 x float> %x) #1 { 108; SSE-LABEL: v4f32_one_step: 109; SSE: # BB#0: 110; SSE-NEXT: rcpps %xmm0, %xmm2 111; SSE-NEXT: mulps %xmm2, %xmm0 112; SSE-NEXT: movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 113; SSE-NEXT: subps %xmm0, %xmm1 114; SSE-NEXT: mulps %xmm2, %xmm1 115; SSE-NEXT: addps %xmm2, %xmm1 116; SSE-NEXT: movaps %xmm1, %xmm0 117; SSE-NEXT: retq 118; 119; AVX-LABEL: v4f32_one_step: 120; AVX: # BB#0: 121; AVX-NEXT: vrcpps %xmm0, %xmm1 122; AVX-NEXT: vmulps %xmm1, %xmm0, %xmm0 123; AVX-NEXT: vmovaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 124; AVX-NEXT: vsubps %xmm0, %xmm2, %xmm0 125; AVX-NEXT: vmulps %xmm0, %xmm1, %xmm0 126; AVX-NEXT: vaddps %xmm0, %xmm1, %xmm0 127; AVX-NEXT: retq 128 %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x 129 ret <4 x float> %div 130} 131 132define <4 x float> @v4f32_two_step(<4 x float> %x) #2 { 133; SSE-LABEL: v4f32_two_step: 134; SSE: # BB#0: 135; SSE-NEXT: rcpps %xmm0, %xmm2 136; SSE-NEXT: movaps %xmm0, %xmm3 137; SSE-NEXT: mulps %xmm2, %xmm3 138; SSE-NEXT: movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 139; SSE-NEXT: movaps %xmm1, %xmm4 140; SSE-NEXT: subps %xmm3, %xmm4 141; SSE-NEXT: mulps %xmm2, %xmm4 142; SSE-NEXT: addps %xmm2, %xmm4 143; SSE-NEXT: mulps %xmm4, %xmm0 144; SSE-NEXT: subps %xmm0, %xmm1 145; SSE-NEXT: mulps %xmm4, %xmm1 146; SSE-NEXT: addps %xmm4, %xmm1 147; SSE-NEXT: movaps %xmm1, %xmm0 148; SSE-NEXT: retq 149; 150; AVX-LABEL: v4f32_two_step: 151; AVX: # BB#0: 152; AVX-NEXT: vrcpps %xmm0, %xmm1 153; AVX-NEXT: vmulps %xmm1, %xmm0, %xmm2 154; AVX-NEXT: vmovaps {{.*#+}} xmm3 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 155; AVX-NEXT: vsubps %xmm2, %xmm3, %xmm2 156; AVX-NEXT: vmulps %xmm2, %xmm1, %xmm2 157; AVX-NEXT: vaddps %xmm2, %xmm1, %xmm1 158; AVX-NEXT: vmulps %xmm1, %xmm0, %xmm0 159; AVX-NEXT: vsubps %xmm0, %xmm3, %xmm0 160; AVX-NEXT: vmulps %xmm0, %xmm1, %xmm0 161; AVX-NEXT: vaddps %xmm0, %xmm1, %xmm0 162; AVX-NEXT: retq 163 %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x 164 ret <4 x float> %div 165} 166 167define <8 x float> @v8f32_no_estimate(<8 x float> %x) #0 { 168; SSE-LABEL: v8f32_no_estimate: 169; SSE: # BB#0: 170; SSE-NEXT: movaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 171; SSE-NEXT: movaps %xmm2, %xmm3 172; SSE-NEXT: divps %xmm0, %xmm3 173; SSE-NEXT: divps %xmm1, %xmm2 174; SSE-NEXT: movaps %xmm3, %xmm0 175; SSE-NEXT: movaps %xmm2, %xmm1 176; SSE-NEXT: retq 177; 178; AVX-LABEL: v8f32_no_estimate: 179; AVX: # BB#0: 180; AVX-NEXT: vmovaps {{.*#+}} ymm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 181; AVX-NEXT: vdivps %ymm0, %ymm1, %ymm0 182; AVX-NEXT: retq 183 %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x 184 ret <8 x float> %div 185} 186 187define <8 x float> @v8f32_one_step(<8 x float> %x) #1 { 188; SSE-LABEL: v8f32_one_step: 189; SSE: # BB#0: 190; SSE-NEXT: rcpps %xmm0, %xmm4 191; SSE-NEXT: mulps %xmm4, %xmm0 192; SSE-NEXT: movaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 193; SSE-NEXT: movaps %xmm2, %xmm3 194; SSE-NEXT: subps %xmm0, %xmm3 195; SSE-NEXT: mulps %xmm4, %xmm3 196; SSE-NEXT: addps %xmm4, %xmm3 197; SSE-NEXT: rcpps %xmm1, %xmm0 198; SSE-NEXT: mulps %xmm0, %xmm1 199; SSE-NEXT: subps %xmm1, %xmm2 200; SSE-NEXT: mulps %xmm0, %xmm2 201; SSE-NEXT: addps %xmm0, %xmm2 202; SSE-NEXT: movaps %xmm3, %xmm0 203; SSE-NEXT: movaps %xmm2, %xmm1 204; SSE-NEXT: retq 205; 206; AVX-LABEL: v8f32_one_step: 207; AVX: # BB#0: 208; AVX-NEXT: vrcpps %ymm0, %ymm1 209; AVX-NEXT: vmulps %ymm1, %ymm0, %ymm0 210; AVX-NEXT: vmovaps {{.*#+}} ymm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 211; AVX-NEXT: vsubps %ymm0, %ymm2, %ymm0 212; AVX-NEXT: vmulps %ymm0, %ymm1, %ymm0 213; AVX-NEXT: vaddps %ymm0, %ymm1, %ymm0 214; AVX-NEXT: retq 215 %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x 216 ret <8 x float> %div 217} 218 219define <8 x float> @v8f32_two_step(<8 x float> %x) #2 { 220; SSE-LABEL: v8f32_two_step: 221; SSE: # BB#0: 222; SSE-NEXT: movaps %xmm1, %xmm2 223; SSE-NEXT: rcpps %xmm0, %xmm3 224; SSE-NEXT: movaps %xmm0, %xmm4 225; SSE-NEXT: mulps %xmm3, %xmm4 226; SSE-NEXT: movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 227; SSE-NEXT: movaps %xmm1, %xmm5 228; SSE-NEXT: subps %xmm4, %xmm5 229; SSE-NEXT: mulps %xmm3, %xmm5 230; SSE-NEXT: addps %xmm3, %xmm5 231; SSE-NEXT: mulps %xmm5, %xmm0 232; SSE-NEXT: movaps %xmm1, %xmm3 233; SSE-NEXT: subps %xmm0, %xmm3 234; SSE-NEXT: mulps %xmm5, %xmm3 235; SSE-NEXT: addps %xmm5, %xmm3 236; SSE-NEXT: rcpps %xmm2, %xmm0 237; SSE-NEXT: movaps %xmm2, %xmm4 238; SSE-NEXT: mulps %xmm0, %xmm4 239; SSE-NEXT: movaps %xmm1, %xmm5 240; SSE-NEXT: subps %xmm4, %xmm5 241; SSE-NEXT: mulps %xmm0, %xmm5 242; SSE-NEXT: addps %xmm0, %xmm5 243; SSE-NEXT: mulps %xmm5, %xmm2 244; SSE-NEXT: subps %xmm2, %xmm1 245; SSE-NEXT: mulps %xmm5, %xmm1 246; SSE-NEXT: addps %xmm5, %xmm1 247; SSE-NEXT: movaps %xmm3, %xmm0 248; SSE-NEXT: retq 249; 250; AVX-LABEL: v8f32_two_step: 251; AVX: # BB#0: 252; AVX-NEXT: vrcpps %ymm0, %ymm1 253; AVX-NEXT: vmulps %ymm1, %ymm0, %ymm2 254; AVX-NEXT: vmovaps {{.*#+}} ymm3 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00] 255; AVX-NEXT: vsubps %ymm2, %ymm3, %ymm2 256; AVX-NEXT: vmulps %ymm2, %ymm1, %ymm2 257; AVX-NEXT: vaddps %ymm2, %ymm1, %ymm1 258; AVX-NEXT: vmulps %ymm1, %ymm0, %ymm0 259; AVX-NEXT: vsubps %ymm0, %ymm3, %ymm0 260; AVX-NEXT: vmulps %ymm0, %ymm1, %ymm0 261; AVX-NEXT: vaddps %ymm0, %ymm1, %ymm0 262; AVX-NEXT: retq 263 %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x 264 ret <8 x float> %div 265} 266 267attributes #0 = { "unsafe-fp-math"="true" "reciprocal-estimates"="!divf,!vec-divf" } 268attributes #1 = { "unsafe-fp-math"="true" "reciprocal-estimates"="divf,vec-divf" } 269attributes #2 = { "unsafe-fp-math"="true" "reciprocal-estimates"="divf:2,vec-divf:2" } 270 271