593 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4declare double @llvm.powi.f64.i32(double, i32)5declare float @llvm.powi.f32.i32(float, i32)6declare double @llvm.powi.f64.i64(double, i64)7declare double @llvm.fabs.f64(double)8declare double @llvm.copysign.f64(double, double)9declare void @use(double)10 11define double @powi_fneg_even_int(double %x) {12; CHECK-LABEL: @powi_fneg_even_int(13; CHECK-NEXT: entry:14; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)15; CHECK-NEXT: ret double [[R]]16;17entry:18 %fneg = fneg double %x19 %r = tail call double @llvm.powi.f64.i32(double %fneg, i32 4)20 ret double %r21}22 23define double @powi_fabs_even_int(double %x) {24; CHECK-LABEL: @powi_fabs_even_int(25; CHECK-NEXT: entry:26; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)27; CHECK-NEXT: ret double [[R]]28;29entry:30 %f = tail call double @llvm.fabs.f64(double %x)31 %r = tail call double @llvm.powi.f64.i32(double %f, i32 4)32 ret double %r33}34 35define double @powi_copysign_even_int(double %x, double %y) {36; CHECK-LABEL: @powi_copysign_even_int(37; CHECK-NEXT: entry:38; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)39; CHECK-NEXT: ret double [[R]]40;41entry:42 %cs = tail call double @llvm.copysign.f64(double %x, double %y)43 %r = tail call double @llvm.powi.f64.i32(double %cs, i32 4)44 ret double %r45}46 47define double @powi_fneg_odd_int(double %x) {48; CHECK-LABEL: @powi_fneg_odd_int(49; CHECK-NEXT: entry:50; CHECK-NEXT: [[FNEG:%.*]] = fneg double [[X:%.*]]51; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[FNEG]], i32 5)52; CHECK-NEXT: ret double [[R]]53;54entry:55 %fneg = fneg double %x56 %r = tail call double @llvm.powi.f64.i32(double %fneg, i32 5)57 ret double %r58}59 60define double @powi_fabs_odd_int(double %x) {61; CHECK-LABEL: @powi_fabs_odd_int(62; CHECK-NEXT: entry:63; CHECK-NEXT: [[F:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])64; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[F]], i32 5)65; CHECK-NEXT: ret double [[R]]66;67entry:68 %f = tail call double @llvm.fabs.f64(double %x)69 %r = tail call double @llvm.powi.f64.i32(double %f, i32 5)70 ret double %r71}72 73define double @powi_copysign_odd_int(double %x, double %y) {74; CHECK-LABEL: @powi_copysign_odd_int(75; CHECK-NEXT: entry:76; CHECK-NEXT: [[CS:%.*]] = tail call double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]])77; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[CS]], i32 5)78; CHECK-NEXT: ret double [[R]]79;80entry:81 %cs = tail call double @llvm.copysign.f64(double %x, double %y)82 %r = tail call double @llvm.powi.f64.i32(double %cs, i32 5)83 ret double %r84}85 86define double @powi_fmul_arg0_no_reassoc(double %x, i32 %i) {87; CHECK-LABEL: @powi_fmul_arg0_no_reassoc(88; CHECK-NEXT: entry:89; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])90; CHECK-NEXT: [[MUL:%.*]] = fmul double [[POW]], [[X]]91; CHECK-NEXT: ret double [[MUL]]92;93entry:94 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)95 %mul = fmul double %pow, %x96 ret double %mul97}98 99 100define double @powi_fmul_arg0(double %x, i32 %i) {101; CHECK-LABEL: @powi_fmul_arg0(102; CHECK-NEXT: entry:103; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])104; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[POW]], [[X]]105; CHECK-NEXT: ret double [[MUL]]106;107entry:108 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)109 %mul = fmul reassoc double %pow, %x110 ret double %mul111}112 113define double @powi_fmul_arg0_use(double %x, i32 %i) {114; CHECK-LABEL: @powi_fmul_arg0_use(115; CHECK-NEXT: entry:116; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])117; CHECK-NEXT: tail call void @use(double [[POW]])118; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[POW]], [[X]]119; CHECK-NEXT: ret double [[MUL]]120;121entry:122 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)123 tail call void @use(double %pow)124 %mul = fmul reassoc double %pow, %x125 ret double %mul126}127 128; Negative test: Missing reassoc flag on fmul129define double @powi_fmul_powi_no_reassoc1(double %x, i32 %y, i32 %z) {130; CHECK-LABEL: @powi_fmul_powi_no_reassoc1(131; CHECK-NEXT: entry:132; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])133; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])134; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]]135; CHECK-NEXT: ret double [[MUL]]136;137entry:138 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)139 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)140 %mul = fmul double %p2, %p1141 ret double %mul142}143 144; Negative test: Missing reassoc flag on 2nd operand145define double @powi_fmul_powi_no_reassoc2(double %x, i32 %y, i32 %z) {146; CHECK-LABEL: @powi_fmul_powi_no_reassoc2(147; CHECK-NEXT: entry:148; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])149; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])150; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]151; CHECK-NEXT: ret double [[MUL]]152;153entry:154 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)155 %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)156 %mul = fmul reassoc double %p2, %p1157 ret double %mul158}159 160; Negative test: Missing reassoc flag on 1st operand161define double @powi_fmul_powi_no_reassoc3(double %x, i32 %y, i32 %z) {162; CHECK-LABEL: @powi_fmul_powi_no_reassoc3(163; CHECK-NEXT: entry:164; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])165; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])166; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]167; CHECK-NEXT: ret double [[MUL]]168;169entry:170 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)171 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)172 %mul = fmul reassoc double %p2, %p1173 ret double %mul174}175 176; All of the fmul and its operands should have the reassoc flags177define double @powi_fmul_powi(double %x, i32 %y, i32 %z) {178; CHECK-LABEL: @powi_fmul_powi(179; CHECK-NEXT: entry:180; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Z:%.*]], [[Y:%.*]]181; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])182; CHECK-NEXT: ret double [[MUL]]183;184entry:185 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)186 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)187 %mul = fmul reassoc double %p2, %p1188 ret double %mul189}190 191define double @powi_fmul_powi_fast_on_fmul(double %x, i32 %y, i32 %z) {192; CHECK-LABEL: @powi_fmul_powi_fast_on_fmul(193; CHECK-NEXT: entry:194; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Z:%.*]], [[Y:%.*]]195; CHECK-NEXT: [[MUL:%.*]] = call fast double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])196; CHECK-NEXT: ret double [[MUL]]197;198entry:199 %p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y)200 %p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z)201 %mul = fmul fast double %p2, %p1202 ret double %mul203}204 205define double @powi_fmul_powi_fast_on_powi(double %x, i32 %y, i32 %z) {206; CHECK-LABEL: @powi_fmul_powi_fast_on_powi(207; CHECK-NEXT: entry:208; CHECK-NEXT: [[P1:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])209; CHECK-NEXT: [[P2:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])210; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]]211; CHECK-NEXT: ret double [[MUL]]212;213entry:214 %p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y)215 %p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z)216 %mul = fmul double %p2, %p1217 ret double %mul218}219 220define double @powi_fmul_powi_same_power(double %x, i32 %y, i32 %z) {221; CHECK-LABEL: @powi_fmul_powi_same_power(222; CHECK-NEXT: entry:223; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[Y:%.*]], 1224; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])225; CHECK-NEXT: ret double [[MUL]]226;227entry:228 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)229 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)230 %mul = fmul reassoc double %p2, %p1231 ret double %mul232}233 234define double @powi_fmul_powi_different_integer_types(double %x, i32 %y, i16 %z) {235; CHECK-LABEL: @powi_fmul_powi_different_integer_types(236; CHECK-NEXT: entry:237; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])238; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i16(double [[X]], i16 [[Z:%.*]])239; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]240; CHECK-NEXT: ret double [[MUL]]241;242entry:243 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)244 %p2 = tail call reassoc double @llvm.powi.f64.i16(double %x, i16 %z)245 %mul = fmul reassoc double %p2, %p1246 ret double %mul247}248 249define double @powi_fmul_powi_use_first(double %x, i32 %y, i32 %z) {250; CHECK-LABEL: @powi_fmul_powi_use_first(251; CHECK-NEXT: entry:252; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])253; CHECK-NEXT: tail call void @use(double [[P1]])254; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y]], [[Z:%.*]]255; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])256; CHECK-NEXT: ret double [[MUL]]257;258entry:259 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)260 tail call void @use(double %p1)261 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)262 %mul = fmul reassoc double %p1, %p2263 ret double %mul264}265 266define double @powi_fmul_powi_use_second(double %x, i32 %y, i32 %z) {267; CHECK-LABEL: @powi_fmul_powi_use_second(268; CHECK-NEXT: entry:269; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]])270; CHECK-NEXT: tail call void @use(double [[P1]])271; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y:%.*]], [[Z]]272; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])273; CHECK-NEXT: ret double [[MUL]]274;275entry:276 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)277 tail call void @use(double %p1)278 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)279 %mul = fmul reassoc double %p2, %p1280 ret double %mul281}282 283define double @powi_fmul_different_base(double %x, double %m, i32 %y, i32 %z) {284; CHECK-LABEL: @powi_fmul_different_base(285; CHECK-NEXT: entry:286; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])287; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[M:%.*]], i32 [[Z:%.*]])288; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]289; CHECK-NEXT: ret double [[MUL]]290;291entry:292 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)293 %p2 = tail call double @llvm.powi.f64.i32(double %m, i32 %z)294 %mul = fmul reassoc double %p2, %p1295 ret double %mul296}297 298define double @different_types_powi(double %x, i32 %y, i64 %z) {299; CHECK-LABEL: @different_types_powi(300; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])301; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i64(double [[X]], i64 [[Z:%.*]])302; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]303; CHECK-NEXT: ret double [[MUL]]304;305 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)306 %p2 = tail call double @llvm.powi.f64.i64(double %x, i64 %z)307 %mul = fmul reassoc double %p2, %p1308 ret double %mul309}310 311define double @fdiv_pow_powi(double %x) {312; CHECK-LABEL: @fdiv_pow_powi(313; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]]314; CHECK-NEXT: ret double [[DIV]]315;316 %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 3)317 %div = fdiv reassoc nnan double %p1, %x318 ret double %div319}320 321define float @fdiv_powf_powi(float %x) {322; CHECK-LABEL: @fdiv_powf_powi(323; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan float @llvm.powi.f32.i32(float [[X:%.*]], i32 99)324; CHECK-NEXT: ret float [[DIV]]325;326 %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100)327 %div = fdiv reassoc nnan float %p1, %x328 ret float %div329}330 331; TODO: Multi-use may be also better off creating Powi(x,y-1) then creating332; (mul, Powi(x,y-1),x) to replace the Powi(x,y).333define double @fdiv_pow_powi_multi_use(double %x) {334; CHECK-LABEL: @fdiv_pow_powi_multi_use(335; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)336; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]337; CHECK-NEXT: tail call void @use(double [[P1]])338; CHECK-NEXT: ret double [[DIV]]339;340 %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)341 %div = fdiv reassoc nnan double %p1, %x342 tail call void @use(double %p1)343 ret double %div344}345 346; Negative test: Miss part of the fmf flag for the fdiv instruction347define float @fdiv_powf_powi_missing_reassoc(float %x) {348; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc(349; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)350; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan float [[P1]], [[X]]351; CHECK-NEXT: ret float [[DIV]]352;353 %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)354 %div = fdiv reassoc nnan float %p1, %x355 ret float %div356}357 358define float @fdiv_powf_powi_missing_reassoc1(float %x) {359; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc1(360; CHECK-NEXT: [[P1:%.*]] = call reassoc float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)361; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]]362; CHECK-NEXT: ret float [[DIV]]363;364 %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100)365 %div = fdiv nnan float %p1, %x366 ret float %div367}368 369define float @fdiv_powf_powi_missing_nnan(float %x) {370; CHECK-LABEL: @fdiv_powf_powi_missing_nnan(371; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)372; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float [[P1]], [[X]]373; CHECK-NEXT: ret float [[DIV]]374;375 %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)376 %div = fdiv reassoc float %p1, %x377 ret float %div378}379 380; Negative test: Illegal because (Y - 1) wraparound381define double @fdiv_pow_powi_negative(double %x) {382; CHECK-LABEL: @fdiv_pow_powi_negative(383; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 -2147483648)384; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]385; CHECK-NEXT: ret double [[DIV]]386;387 %p1 = call double @llvm.powi.f64.i32(double %x, i32 -2147483648) ; INT_MIN388 %div = fdiv reassoc nnan double %p1, %x389 ret double %div390}391 392; Negative test: The 2nd powi argument is a variable393define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) {394; CHECK-LABEL: @fdiv_pow_powi_negative_variable(395; CHECK-NEXT: [[P1:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])396; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]397; CHECK-NEXT: ret double [[DIV]]398;399 %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)400 %div = fdiv reassoc nnan double %p1, %x401 ret double %div402}403 404; powi(X,C1)/ (X * Z) --> powi(X,C1 - 1)/ Z405define double @fdiv_fmul_powi(double %a, double %z) {406; CHECK-LABEL: @fdiv_fmul_powi(407; CHECK-NEXT: [[TMP1:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 4)408; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[TMP1]], [[Z:%.*]]409; CHECK-NEXT: ret double [[DIV]]410;411 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)412 %square = fmul reassoc double %z, %a413 %div = fdiv reassoc nnan double %pow, %square414 ret double %div415}416 417; powi(X, 5)/ (X * X) --> powi(X, 4)/ X -> powi(X, 3)418define double @fdiv_fmul_powi_2(double %a) {419; CHECK-LABEL: @fdiv_fmul_powi_2(420; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 3)421; CHECK-NEXT: ret double [[DIV]]422;423 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)424 %square = fmul reassoc double %a, %a425 %div = fdiv reassoc nnan double %pow, %square426 ret double %div427}428 429define <2 x float> @fdiv_fmul_powi_vector(<2 x float> %a) {430; CHECK-LABEL: @fdiv_fmul_powi_vector(431; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan <2 x float> @llvm.powi.v2f32.i32(<2 x float> [[A:%.*]], i32 3)432; CHECK-NEXT: ret <2 x float> [[DIV]]433;434 %pow = call reassoc <2 x float> @llvm.powi.v2f32.i32(<2 x float> %a, i32 5)435 %square = fmul reassoc <2 x float> %a, %a436 %div = fdiv reassoc nnan <2 x float> %pow, %square437 ret <2 x float> %div438}439 440; Negative test441define double @fdiv_fmul_powi_missing_reassoc1(double %a) {442; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc1(443; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)444; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]445; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan double [[POW]], [[SQUARE]]446; CHECK-NEXT: ret double [[DIV]]447;448 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)449 %square = fmul reassoc double %a, %a450 %div = fdiv nnan double %pow, %square451 ret double %div452}453 454define double @fdiv_fmul_powi_missing_reassoc2(double %a) {455; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc2(456; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)457; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[A]], [[A]]458; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]459; CHECK-NEXT: ret double [[DIV]]460;461 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)462 %square = fmul double %a, %a463 %div = fdiv reassoc nnan double %pow, %square464 ret double %div465}466 467define double @fdiv_fmul_powi_missing_reassoc3(double %a) {468; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc3(469; CHECK-NEXT: [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)470; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]471; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]472; CHECK-NEXT: ret double [[DIV]]473;474 %pow = call double @llvm.powi.f64.i32(double %a, i32 5)475 %square = fmul reassoc double %a, %a476 %div = fdiv reassoc nnan double %pow, %square477 ret double %div478}479 480define double @fdiv_fmul_powi_missing_nnan(double %a) {481; CHECK-LABEL: @fdiv_fmul_powi_missing_nnan(482; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)483; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]484; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[POW]], [[SQUARE]]485; CHECK-NEXT: ret double [[DIV]]486;487 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)488 %square = fmul reassoc double %a, %a489 %div = fdiv reassoc double %pow, %square490 ret double %div491}492 493define double @fdiv_fmul_powi_negative_wrap(double noundef %x) {494; CHECK-LABEL: @fdiv_fmul_powi_negative_wrap(495; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 -2147483648)496; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]497; CHECK-NEXT: ret double [[MUL]]498;499 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 -2147483648) ; INT_MIN500 %mul = fmul reassoc double %p1, %x501 ret double %mul502}503 504define double @fdiv_fmul_powi_multi_use(double %a) {505; CHECK-LABEL: @fdiv_fmul_powi_multi_use(506; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)507; CHECK-NEXT: tail call void @use(double [[POW]])508; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]509; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]510; CHECK-NEXT: ret double [[DIV]]511;512 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)513 tail call void @use(double %pow)514 %square = fmul reassoc double %a, %a515 %div = fdiv reassoc nnan double %pow, %square516 ret double %div517}518 519; powi(X, Y) * X --> powi(X, Y+1)520define double @powi_fmul_powi_x(double noundef %x) {521; CHECK-LABEL: @powi_fmul_powi_x(522; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)523; CHECK-NEXT: ret double [[MUL]]524;525 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 3)526 %mul = fmul reassoc double %p1, %x527 ret double %mul528}529 530; Negative test: Multi-use531define double @powi_fmul_powi_x_multi_use(double noundef %x) {532; CHECK-LABEL: @powi_fmul_powi_x_multi_use(533; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)534; CHECK-NEXT: tail call void @use(double [[P1]])535; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]536; CHECK-NEXT: ret double [[MUL]]537;538 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)539 tail call void @use(double %p1)540 %mul = fmul reassoc double %p1, %x541 ret double %mul542}543 544; Negative test: Miss fmf flag545define double @powi_fmul_powi_x_missing_reassoc(double noundef %x) {546; CHECK-LABEL: @powi_fmul_powi_x_missing_reassoc(547; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)548; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P1]], [[X]]549; CHECK-NEXT: ret double [[MUL]]550;551 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)552 %mul = fmul double %p1, %x553 ret double %mul554}555 556; Negative test: overflow557define double @powi_fmul_powi_x_overflow(double noundef %x) {558; CHECK-LABEL: @powi_fmul_powi_x_overflow(559; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 2147483647)560; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]561; CHECK-NEXT: ret double [[MUL]]562;563 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 2147483647) ; INT_MAX564 %mul = fmul reassoc double %p1, %x565 ret double %mul566}567 568define <3 x float> @powi_unary_shuffle_ops(<3 x float> %x, i32 %power) {569; CHECK-LABEL: @powi_unary_shuffle_ops(570; CHECK-NEXT: [[TMP1:%.*]] = call <3 x float> @llvm.powi.v3f32.i32(<3 x float> [[X:%.*]], i32 [[POWER:%.*]])571; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x float> [[TMP1]], <3 x float> poison, <3 x i32> <i32 1, i32 0, i32 2>572; CHECK-NEXT: ret <3 x float> [[R]]573;574 %sx = shufflevector <3 x float> %x, <3 x float> poison, <3 x i32> <i32 1, i32 0, i32 2>575 %r = call <3 x float> @llvm.powi(<3 x float> %sx, i32 %power)576 ret <3 x float> %r577}578 579; Negative test - multiple uses580 581define <3 x float> @powi_unary_shuffle_ops_use(<3 x float> %x, i32 %power, ptr %p) {582; CHECK-LABEL: @powi_unary_shuffle_ops_use(583; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x float> [[X:%.*]], <3 x float> poison, <3 x i32> <i32 1, i32 0, i32 2>584; CHECK-NEXT: store <3 x float> [[SX]], ptr [[P:%.*]], align 16585; CHECK-NEXT: [[R:%.*]] = call <3 x float> @llvm.powi.v3f32.i32(<3 x float> [[SX]], i32 [[POWER:%.*]])586; CHECK-NEXT: ret <3 x float> [[R]]587;588 %sx = shufflevector <3 x float> %x, <3 x float> poison, <3 x i32> <i32 1, i32 0, i32 2>589 store <3 x float> %sx, ptr %p590 %r = call <3 x float> @llvm.powi(<3 x float> %sx, i32 %power)591 ret <3 x float> %r592}593