1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes='function(scalarizer)' %s | FileCheck %s 3 4; Unary fp 5declare <2 x float> @llvm.sqrt.v2f32(<2 x float>) 6 7; Binary fp 8declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>) 9declare <2 x float> @llvm.minimum.v2f32(<2 x float>, <2 x float>) 10declare <2 x float> @llvm.maximum.v2f32(<2 x float>, <2 x float>) 11 12; Ternary fp 13declare <2 x float> @llvm.fma.v2f32(<2 x float>, <2 x float>, <2 x float>) 14 15; Unary int 16declare <2 x i32> @llvm.bswap.v2i32(<2 x i32>) 17 18; Unary int plus constant scalar operand 19declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) 20 21; Unary fp plus any scalar operand 22declare <2 x float> @llvm.powi.v2f32.i32(<2 x float>, i32) 23 24; Binary int plus constant scalar operand 25declare <2 x i32> @llvm.smul.fix.sat.v2i32(<2 x i32>, <2 x i32>, i32) 26declare <2 x i32> @llvm.umul.fix.sat.v2i32(<2 x i32>, <2 x i32>, i32) 27 28; Unary fp operand, int return type 29declare <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float>) 30declare <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float>) 31 32; Unary fp operand, int return type 33declare <2 x i32> @llvm.lrint.v2i32.v2f32(<2 x float>) 34declare <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float>) 35 36; Bool return type, overloaded on fp operand type 37declare <2 x i1> @llvm.is.fpclass(<2 x float>, i32) 38 39 40define <2 x float> @scalarize_sqrt_v2f32(<2 x float> %x) #0 { 41; CHECK-LABEL: @scalarize_sqrt_v2f32( 42; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 43; CHECK-NEXT: [[SQRT_I0:%.*]] = call float @llvm.sqrt.f32(float [[X_I0]]) 44; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 45; CHECK-NEXT: [[SQRT_I1:%.*]] = call float @llvm.sqrt.f32(float [[X_I1]]) 46; CHECK-NEXT: [[SQRT_UPTO0:%.*]] = insertelement <2 x float> poison, float [[SQRT_I0]], i64 0 47; CHECK-NEXT: [[SQRT:%.*]] = insertelement <2 x float> [[SQRT_UPTO0]], float [[SQRT_I1]], i64 1 48; CHECK-NEXT: ret <2 x float> [[SQRT]] 49; 50 %sqrt = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x) 51 ret <2 x float> %sqrt 52} 53 54define <2 x float> @scalarize_minnum_v2f32(<2 x float> %x, <2 x float> %y) #0 { 55; CHECK-LABEL: @scalarize_minnum_v2f32( 56; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 57; CHECK-NEXT: [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0 58; CHECK-NEXT: [[MINNUM_I0:%.*]] = call float @llvm.minnum.f32(float [[X_I0]], float [[Y_I0]]) 59; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 60; CHECK-NEXT: [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1 61; CHECK-NEXT: [[MINNUM_I1:%.*]] = call float @llvm.minnum.f32(float [[X_I1]], float [[Y_I1]]) 62; CHECK-NEXT: [[MINNUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MINNUM_I0]], i64 0 63; CHECK-NEXT: [[MINNUM:%.*]] = insertelement <2 x float> [[MINNUM_UPTO0]], float [[MINNUM_I1]], i64 1 64; CHECK-NEXT: ret <2 x float> [[MINNUM]] 65; 66 %minnum = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y) 67 ret <2 x float> %minnum 68} 69 70define <2 x float> @scalarize_minimum_v2f32(<2 x float> %x, <2 x float> %y) #0 { 71; CHECK-LABEL: @scalarize_minimum_v2f32( 72; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 73; CHECK-NEXT: [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0 74; CHECK-NEXT: [[MINIMUM_I0:%.*]] = call float @llvm.minimum.f32(float [[X_I0]], float [[Y_I0]]) 75; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 76; CHECK-NEXT: [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1 77; CHECK-NEXT: [[MINIMUM_I1:%.*]] = call float @llvm.minimum.f32(float [[X_I1]], float [[Y_I1]]) 78; CHECK-NEXT: [[MINIMUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MINIMUM_I0]], i64 0 79; CHECK-NEXT: [[MINIMUM:%.*]] = insertelement <2 x float> [[MINIMUM_UPTO0]], float [[MINIMUM_I1]], i64 1 80; CHECK-NEXT: ret <2 x float> [[MINIMUM]] 81; 82 %minimum = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> %y) 83 ret <2 x float> %minimum 84} 85 86define <2 x float> @scalarize_maximum_v2f32(<2 x float> %x, <2 x float> %y) #0 { 87; CHECK-LABEL: @scalarize_maximum_v2f32( 88; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 89; CHECK-NEXT: [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0 90; CHECK-NEXT: [[MAXIMUM_I0:%.*]] = call float @llvm.maximum.f32(float [[X_I0]], float [[Y_I0]]) 91; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 92; CHECK-NEXT: [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1 93; CHECK-NEXT: [[MAXIMUM_I1:%.*]] = call float @llvm.maximum.f32(float [[X_I1]], float [[Y_I1]]) 94; CHECK-NEXT: [[MAXIMUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MAXIMUM_I0]], i64 0 95; CHECK-NEXT: [[MAXIMUM:%.*]] = insertelement <2 x float> [[MAXIMUM_UPTO0]], float [[MAXIMUM_I1]], i64 1 96; CHECK-NEXT: ret <2 x float> [[MAXIMUM]] 97; 98 %maximum = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> %y) 99 ret <2 x float> %maximum 100} 101 102define <2 x float> @scalarize_fma_v2f32(<2 x float> %x, <2 x float> %y, <2 x float> %z) #0 { 103; CHECK-LABEL: @scalarize_fma_v2f32( 104; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 105; CHECK-NEXT: [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0 106; CHECK-NEXT: [[Z_I0:%.*]] = extractelement <2 x float> [[Z:%.*]], i64 0 107; CHECK-NEXT: [[FMA_I0:%.*]] = call float @llvm.fma.f32(float [[X_I0]], float [[Y_I0]], float [[Z_I0]]) 108; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 109; CHECK-NEXT: [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1 110; CHECK-NEXT: [[Z_I1:%.*]] = extractelement <2 x float> [[Z]], i64 1 111; CHECK-NEXT: [[FMA_I1:%.*]] = call float @llvm.fma.f32(float [[X_I1]], float [[Y_I1]], float [[Z_I1]]) 112; CHECK-NEXT: [[FMA_UPTO0:%.*]] = insertelement <2 x float> poison, float [[FMA_I0]], i64 0 113; CHECK-NEXT: [[FMA:%.*]] = insertelement <2 x float> [[FMA_UPTO0]], float [[FMA_I1]], i64 1 114; CHECK-NEXT: ret <2 x float> [[FMA]] 115; 116 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> %y, <2 x float> %z) 117 ret <2 x float> %fma 118} 119 120define <2 x i32> @scalarize_bswap_v2i32(<2 x i32> %x) #0 { 121; CHECK-LABEL: @scalarize_bswap_v2i32( 122; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0 123; CHECK-NEXT: [[BSWAP_I0:%.*]] = call i32 @llvm.bswap.i32(i32 [[X_I0]]) 124; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1 125; CHECK-NEXT: [[BSWAP_I1:%.*]] = call i32 @llvm.bswap.i32(i32 [[X_I1]]) 126; CHECK-NEXT: [[BSWAP_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[BSWAP_I0]], i64 0 127; CHECK-NEXT: [[BSWAP:%.*]] = insertelement <2 x i32> [[BSWAP_UPTO0]], i32 [[BSWAP_I1]], i64 1 128; CHECK-NEXT: ret <2 x i32> [[BSWAP]] 129; 130 %bswap = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %x) 131 ret <2 x i32> %bswap 132} 133 134define <2 x i32> @scalarize_ctlz_v2i32(<2 x i32> %x) #0 { 135; CHECK-LABEL: @scalarize_ctlz_v2i32( 136; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0 137; CHECK-NEXT: [[CTLZ_I0:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X_I0]], i1 true) 138; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1 139; CHECK-NEXT: [[CTLZ_I1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X_I1]], i1 true) 140; CHECK-NEXT: [[CTLZ_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[CTLZ_I0]], i64 0 141; CHECK-NEXT: [[CTLZ:%.*]] = insertelement <2 x i32> [[CTLZ_UPTO0]], i32 [[CTLZ_I1]], i64 1 142; CHECK-NEXT: ret <2 x i32> [[CTLZ]] 143; 144 %ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 true) 145 ret <2 x i32> %ctlz 146} 147 148define <2 x float> @scalarize_powi_v2f32(<2 x float> %x, i32 %y) #0 { 149; CHECK-LABEL: @scalarize_powi_v2f32( 150; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 151; CHECK-NEXT: [[POWI_I0:%.*]] = call float @llvm.powi.f32.i32(float [[X_I0]], i32 [[Y:%.*]]) 152; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 153; CHECK-NEXT: [[POWI_I1:%.*]] = call float @llvm.powi.f32.i32(float [[X_I1]], i32 [[Y]]) 154; CHECK-NEXT: [[POWI_UPTO0:%.*]] = insertelement <2 x float> poison, float [[POWI_I0]], i64 0 155; CHECK-NEXT: [[POWI:%.*]] = insertelement <2 x float> [[POWI_UPTO0]], float [[POWI_I1]], i64 1 156; CHECK-NEXT: ret <2 x float> [[POWI]] 157; 158 %powi = call <2 x float> @llvm.powi.v2f32.i32(<2 x float> %x, i32 %y) 159 ret <2 x float> %powi 160} 161 162define <2 x i32> @scalarize_smul_fix_sat_v2i32(<2 x i32> %x) #0 { 163; CHECK-LABEL: @scalarize_smul_fix_sat_v2i32( 164; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0 165; CHECK-NEXT: [[SMULFIXSAT_I0:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[X_I0]], i32 5, i32 31) 166; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1 167; CHECK-NEXT: [[SMULFIXSAT_I1:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[X_I1]], i32 19, i32 31) 168; CHECK-NEXT: [[SMULFIXSAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SMULFIXSAT_I0]], i64 0 169; CHECK-NEXT: [[SMULFIXSAT:%.*]] = insertelement <2 x i32> [[SMULFIXSAT_UPTO0]], i32 [[SMULFIXSAT_I1]], i64 1 170; CHECK-NEXT: ret <2 x i32> [[SMULFIXSAT]] 171; 172 %smulfixsat = call <2 x i32> @llvm.smul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> <i32 5, i32 19>, i32 31) 173 ret <2 x i32> %smulfixsat 174} 175 176define <2 x i32> @scalarize_umul_fix_sat_v2i32(<2 x i32> %x) #0 { 177; CHECK-LABEL: @scalarize_umul_fix_sat_v2i32( 178; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0 179; CHECK-NEXT: [[UMULFIXSAT_I0:%.*]] = call i32 @llvm.umul.fix.sat.i32(i32 [[X_I0]], i32 5, i32 31) 180; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1 181; CHECK-NEXT: [[UMULFIXSAT_I1:%.*]] = call i32 @llvm.umul.fix.sat.i32(i32 [[X_I1]], i32 19, i32 31) 182; CHECK-NEXT: [[UMULFIXSAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[UMULFIXSAT_I0]], i64 0 183; CHECK-NEXT: [[UMULFIXSAT:%.*]] = insertelement <2 x i32> [[UMULFIXSAT_UPTO0]], i32 [[UMULFIXSAT_I1]], i64 1 184; CHECK-NEXT: ret <2 x i32> [[UMULFIXSAT]] 185; 186 %umulfixsat = call <2 x i32> @llvm.umul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> <i32 5, i32 19>, i32 31) 187 ret <2 x i32> %umulfixsat 188} 189 190define <2 x i32> @scalarize_fptosi_sat(<2 x float> %x) #0 { 191; CHECK-LABEL: @scalarize_fptosi_sat( 192; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 193; CHECK-NEXT: [[SAT_I0:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[X_I0]]) 194; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 195; CHECK-NEXT: [[SAT_I1:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[X_I1]]) 196; CHECK-NEXT: [[SAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SAT_I0]], i64 0 197; CHECK-NEXT: [[SAT:%.*]] = insertelement <2 x i32> [[SAT_UPTO0]], i32 [[SAT_I1]], i64 1 198; CHECK-NEXT: ret <2 x i32> [[SAT]] 199; 200 %sat = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> %x) 201 ret <2 x i32> %sat 202} 203 204define <2 x i32> @scalarize_fptoui_sat(<2 x float> %x) #0 { 205; CHECK-LABEL: @scalarize_fptoui_sat( 206; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 207; CHECK-NEXT: [[SAT_I0:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[X_I0]]) 208; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 209; CHECK-NEXT: [[SAT_I1:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[X_I1]]) 210; CHECK-NEXT: [[SAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SAT_I0]], i64 0 211; CHECK-NEXT: [[SAT:%.*]] = insertelement <2 x i32> [[SAT_UPTO0]], i32 [[SAT_I1]], i64 1 212; CHECK-NEXT: ret <2 x i32> [[SAT]] 213; 214 %sat = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float> %x) 215 ret <2 x i32> %sat 216} 217 218define <2 x i32> @scalarize_lrint(<2 x float> %x) #0 { 219; CHECK-LABEL: @scalarize_lrint( 220; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 221; CHECK-NEXT: [[RND_I0:%.*]] = call i32 @llvm.lrint.i32.f32(float [[X_I0]]) 222; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 223; CHECK-NEXT: [[RND_I1:%.*]] = call i32 @llvm.lrint.i32.f32(float [[X_I1]]) 224; CHECK-NEXT: [[RND_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[RND_I0]], i64 0 225; CHECK-NEXT: [[RND:%.*]] = insertelement <2 x i32> [[RND_UPTO0]], i32 [[RND_I1]], i64 1 226; CHECK-NEXT: ret <2 x i32> [[RND]] 227; 228 %rnd = call <2 x i32> @llvm.lrint.v2i32.v2f32(<2 x float> %x) 229 ret <2 x i32> %rnd 230} 231 232define <2 x i32> @scalarize_llrint(<2 x float> %x) #0 { 233; CHECK-LABEL: @scalarize_llrint( 234; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 235; CHECK-NEXT: [[RND_I0:%.*]] = call i32 @llvm.llrint.i32.f32(float [[X_I0]]) 236; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 237; CHECK-NEXT: [[RND_I1:%.*]] = call i32 @llvm.llrint.i32.f32(float [[X_I1]]) 238; CHECK-NEXT: [[RND_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[RND_I0]], i64 0 239; CHECK-NEXT: [[RND:%.*]] = insertelement <2 x i32> [[RND_UPTO0]], i32 [[RND_I1]], i64 1 240; CHECK-NEXT: ret <2 x i32> [[RND]] 241; 242 %rnd = call <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float> %x) 243 ret <2 x i32> %rnd 244} 245 246define <2 x i1> @scalarize_is_fpclass(<2 x float> %x) #0 { 247; CHECK-LABEL: @scalarize_is_fpclass( 248; CHECK-NEXT: [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0 249; CHECK-NEXT: [[ISFPCLASS_I0:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X_I0]], i32 123) 250; CHECK-NEXT: [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1 251; CHECK-NEXT: [[ISFPCLASS_I1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X_I1]], i32 123) 252; CHECK-NEXT: [[ISFPCLASS_UPTO0:%.*]] = insertelement <2 x i1> poison, i1 [[ISFPCLASS_I0]], i64 0 253; CHECK-NEXT: [[ISFPCLASS:%.*]] = insertelement <2 x i1> [[ISFPCLASS_UPTO0]], i1 [[ISFPCLASS_I1]], i64 1 254; CHECK-NEXT: ret <2 x i1> [[ISFPCLASS]] 255; 256 %isfpclass = call <2 x i1> @llvm.is.fpclass(<2 x float> %x, i32 123) 257 ret <2 x i1> %isfpclass 258} 259