diff --git a/llvm/test/Transforms/VectorCombine/X86/extract-fneg-insert.ll b/llvm/test/Transforms/VectorCombine/X86/extract-fneg-insert.ll new file mode 100644 index 0000000000000..05670cabace62 --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/X86/extract-fneg-insert.ll @@ -0,0 +1,117 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=SSE2 | FileCheck %s --check-prefixes=CHECK,SSE +; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=AVX2 | FileCheck %s --check-prefixes=CHECK,AVX + +declare void @use(float) + +define <4 x float> @ext0_v4f32(<4 x float> %x, <4 x float> %y) { +; CHECK-LABEL: @ext0_v4f32( +; CHECK-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0 +; CHECK-NEXT: [[N:%.*]] = fneg float [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[N]], i32 0 +; CHECK-NEXT: ret <4 x float> [[R]] +; + %e = extractelement <4 x float> %x, i32 0 + %n = fneg float %e + %r = insertelement <4 x float> %y, float %n, i32 0 + ret <4 x float> %r +} + +; Eliminating extract/insert is profitable. + +define <4 x float> @ext2_v4f32(<4 x float> %x, <4 x float> %y) { +; CHECK-LABEL: @ext2_v4f32( +; CHECK-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 2 +; CHECK-NEXT: [[N:%.*]] = fneg float [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[N]], i32 2 +; CHECK-NEXT: ret <4 x float> [[R]] +; + %e = extractelement <4 x float> %x, i32 2 + %n = fneg float %e + %r = insertelement <4 x float> %y, float %n, i32 2 + ret <4 x float> %r +} + +; Eliminating extract/insert is still profitable. Flags propagate. + +define <2 x double> @ext1_v2f64(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: @ext1_v2f64( +; CHECK-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1 +; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x double> [[Y:%.*]], double [[N]], i32 1 +; CHECK-NEXT: ret <2 x double> [[R]] +; + %e = extractelement <2 x double> %x, i32 1 + %n = fneg nsz double %e + %r = insertelement <2 x double> %y, double %n, i32 1 + ret <2 x double> %r +} + +define <8 x float> @ext7_v8f32(<8 x float> %x, <8 x float> %y) { +; CHECK-LABEL: @ext7_v8f32( +; CHECK-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7 +; CHECK-NEXT: [[N:%.*]] = fneg float [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 7 +; CHECK-NEXT: ret <8 x float> [[R]] +; + %e = extractelement <8 x float> %x, i32 7 + %n = fneg float %e + %r = insertelement <8 x float> %y, float %n, i32 7 + ret <8 x float> %r +} + +define <8 x float> @ext7_v8f32_use1(<8 x float> %x, <8 x float> %y) { +; CHECK-LABEL: @ext7_v8f32_use1( +; CHECK-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 5 +; CHECK-NEXT: call void @use(float [[E]]) +; CHECK-NEXT: [[N:%.*]] = fneg float [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 5 +; CHECK-NEXT: ret <8 x float> [[R]] +; + %e = extractelement <8 x float> %x, i32 5 + call void @use(float %e) + %n = fneg float %e + %r = insertelement <8 x float> %y, float %n, i32 5 + ret <8 x float> %r +} + +define <8 x float> @ext7_v8f32_use2(<8 x float> %x, <8 x float> %y) { +; CHECK-LABEL: @ext7_v8f32_use2( +; CHECK-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 3 +; CHECK-NEXT: [[N:%.*]] = fneg float [[E]] +; CHECK-NEXT: call void @use(float [[N]]) +; CHECK-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 3 +; CHECK-NEXT: ret <8 x float> [[R]] +; + %e = extractelement <8 x float> %x, i32 3 + %n = fneg float %e + call void @use(float %n) + %r = insertelement <8 x float> %y, float %n, i32 3 + ret <8 x float> %r +} + +define <2 x double> @ext_index_var_v2f64(<2 x double> %x, <2 x double> %y, i32 %index) { +; CHECK-LABEL: @ext_index_var_v2f64( +; CHECK-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 [[INDEX:%.*]] +; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x double> [[Y:%.*]], double [[N]], i32 [[INDEX]] +; CHECK-NEXT: ret <2 x double> [[R]] +; + %e = extractelement <2 x double> %x, i32 %index + %n = fneg nsz double %e + %r = insertelement <2 x double> %y, double %n, i32 %index + ret <2 x double> %r +} + +define <2 x double> @ext1_v2f64_ins0(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: @ext1_v2f64_ins0( +; CHECK-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1 +; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]] +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x double> [[Y:%.*]], double [[N]], i32 0 +; CHECK-NEXT: ret <2 x double> [[R]] +; + %e = extractelement <2 x double> %x, i32 1 + %n = fneg nsz double %e + %r = insertelement <2 x double> %y, double %n, i32 0 + ret <2 x double> %r +}