323 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare double @llvm.pow.f64(double, double)5declare void @use(double)6 7; negative test for:8; pow(a,b) * a --> pow(a, b+1) (requires reassoc)9 10define double @pow_ab_a(double %a, double %b) {11; CHECK-LABEL: @pow_ab_a(12; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])13; CHECK-NEXT: [[M:%.*]] = fmul double [[P]], [[A]]14; CHECK-NEXT: ret double [[M]]15;16 %p = call double @llvm.pow.f64(double %a, double %b)17 %m = fmul double %p, %a18 ret double %m19}20 21; pow(a,b) * a --> pow(a, b+1)22 23define double @pow_ab_a_reassoc(double %a, double %b) {24; CHECK-LABEL: @pow_ab_a_reassoc(25; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], 1.000000e+0026; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])27; CHECK-NEXT: ret double [[M]]28;29 %p = call double @llvm.pow.f64(double %a, double %b)30 %m = fmul reassoc double %p, %a31 ret double %m32}33 34; a * pow(a,b) --> pow(a, b+1)35 36define double @pow_ab_a_reassoc_commute(double %pa, double %b) {37; CHECK-LABEL: @pow_ab_a_reassoc_commute(38; CHECK-NEXT: [[A:%.*]] = fadd double [[PA:%.*]], 4.200000e+0139; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], 1.000000e+0040; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[TMP1]])41; CHECK-NEXT: ret double [[M]]42;43 %a = fadd double %pa, 42.0 ; thwart complexity-based canonicalization44 %p = call double @llvm.pow.f64(double %a, double %b)45 %m = fmul reassoc double %a, %p46 ret double %m47}48 49; negative test - extra uses not allowed50 51define double @pow_ab_a_reassoc_use(double %a, double %b) {52; CHECK-LABEL: @pow_ab_a_reassoc_use(53; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])54; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[P]], [[A]]55; CHECK-NEXT: call void @use(double [[P]])56; CHECK-NEXT: ret double [[M]]57;58 %p = call double @llvm.pow.f64(double %a, double %b)59 %m = fmul reassoc double %p, %a60 call void @use(double %p)61 ret double %m62}63 64; negative test for:65; pow(a,b) * 1.0/a --> pow(a, b-1) (requires reassoc)66 67define double @pow_ab_recip_a(double %a, double %b) {68; CHECK-LABEL: @pow_ab_recip_a(69; CHECK-NEXT: [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]70; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A]], double [[B:%.*]])71; CHECK-NEXT: [[M:%.*]] = fmul double [[R]], [[P]]72; CHECK-NEXT: ret double [[M]]73;74 %r = fdiv double 1.0, %a75 %p = call double @llvm.pow.f64(double %a, double %b)76 %m = fmul double %r, %p77 ret double %m78}79 80; pow(a,b) / a --> pow(a, b-1) (requires reassoc)81 82define double @pow_ab_recip_a_reassoc(double %a, double %b) {83; CHECK-LABEL: @pow_ab_recip_a_reassoc(84; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+0085; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])86; CHECK-NEXT: ret double [[M]]87;88 %r = fdiv reassoc double 1.0, %a89 %p = call reassoc double @llvm.pow.f64(double %a, double %b)90 %m = fmul reassoc double %r, %p91 ret double %m92}93 94; pow(a,b) / a --> pow(a, b-1) (requires reassoc)95 96define double @pow_ab_recip_a_reassoc_commute(double %a, double %b) {97; CHECK-LABEL: @pow_ab_recip_a_reassoc_commute(98; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+0099; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])100; CHECK-NEXT: ret double [[M]]101;102 %r = fdiv reassoc double 1.0, %a103 %p = call reassoc double @llvm.pow.f64(double %a, double %b)104 %m = fmul reassoc double %p, %r105 ret double %m106}107 108; TODO: extra use prevents conversion to fmul, so this needs a different pattern match.109 110define double @pow_ab_recip_a_reassoc_use1(double %a, double %b) {111; CHECK-LABEL: @pow_ab_recip_a_reassoc_use1(112; CHECK-NEXT: [[R:%.*]] = fdiv reassoc double 1.000000e+00, [[A:%.*]]113; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[B:%.*]])114; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[R]], [[P]]115; CHECK-NEXT: call void @use(double [[R]])116; CHECK-NEXT: ret double [[M]]117;118 %r = fdiv reassoc double 1.0, %a119 %p = call reassoc double @llvm.pow.f64(double %a, double %b)120 %m = fmul reassoc double %r, %p121 call void @use(double %r)122 ret double %m123}124 125; negative test - extra pow uses not allowed126 127define double @pow_ab_recip_a_reassoc_use2(double %a, double %b) {128; CHECK-LABEL: @pow_ab_recip_a_reassoc_use2(129; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])130; CHECK-NEXT: [[M:%.*]] = fdiv reassoc double [[P]], [[A]]131; CHECK-NEXT: call void @use(double [[P]])132; CHECK-NEXT: ret double [[M]]133;134 %r = fdiv reassoc double 1.0, %a135 %p = call reassoc double @llvm.pow.f64(double %a, double %b)136 %m = fmul reassoc double %r, %p137 call void @use(double %p)138 ret double %m139}140 141; negative test - extra pow uses not allowed142 143define double @pow_ab_recip_a_reassoc_use3(double %a, double %b) {144; CHECK-LABEL: @pow_ab_recip_a_reassoc_use3(145; CHECK-NEXT: [[R:%.*]] = fdiv reassoc double 1.000000e+00, [[A:%.*]]146; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[B:%.*]])147; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[R]], [[P]]148; CHECK-NEXT: call void @use(double [[R]])149; CHECK-NEXT: call void @use(double [[P]])150; CHECK-NEXT: ret double [[M]]151;152 %r = fdiv reassoc double 1.0, %a153 %p = call reassoc double @llvm.pow.f64(double %a, double %b)154 %m = fmul reassoc double %r, %p155 call void @use(double %r)156 call void @use(double %p)157 ret double %m158}159 160; negative test for:161; (a**b) * (c**b) --> (a*c) ** b (if mul is reassoc)162 163define double @pow_ab_pow_cb(double %a, double %b, double %c) {164; CHECK-LABEL: @pow_ab_pow_cb(165; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])166; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])167; CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP2]], [[TMP1]]168; CHECK-NEXT: ret double [[MUL]]169;170 %1 = call double @llvm.pow.f64(double %a, double %b)171 %2 = call double @llvm.pow.f64(double %c, double %b)172 %mul = fmul double %2, %1173 ret double %mul174}175 176; (a**b) * (c**b) --> (a*c) ** b177 178define double @pow_ab_pow_cb_reassoc(double %a, double %b, double %c) {179; CHECK-LABEL: @pow_ab_pow_cb_reassoc(180; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[C:%.*]], [[A:%.*]]181; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B:%.*]])182; CHECK-NEXT: ret double [[MUL]]183;184 %1 = call double @llvm.pow.f64(double %a, double %b)185 %2 = call double @llvm.pow.f64(double %c, double %b)186 %mul = fmul reassoc double %2, %1187 ret double %mul188}189 190; (a**b) * (c**b) --> (a*c) ** b191 192define double @pow_ab_pow_cb_reassoc_use1(double %a, double %b, double %c) {193; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use1(194; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])195; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A]], [[C:%.*]]196; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])197; CHECK-NEXT: call void @use(double [[AB]])198; CHECK-NEXT: ret double [[MUL]]199;200 %ab = call double @llvm.pow.f64(double %a, double %b)201 %cb = call double @llvm.pow.f64(double %c, double %b)202 %mul = fmul reassoc double %ab, %cb203 call void @use(double %ab)204 ret double %mul205}206 207; (a**b) * (c**b) --> (a*c) ** b208 209define double @pow_ab_pow_cb_reassoc_use2(double %a, double %b, double %c) {210; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use2(211; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B:%.*]])212; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A:%.*]], [[C]]213; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])214; CHECK-NEXT: call void @use(double [[CB]])215; CHECK-NEXT: ret double [[MUL]]216;217 %ab = call double @llvm.pow.f64(double %a, double %b)218 %cb = call double @llvm.pow.f64(double %c, double %b)219 %mul = fmul reassoc double %ab, %cb220 call void @use(double %cb)221 ret double %mul222}223 224; negative test - too many extra uses225 226define double @pow_ab_pow_cb_reassoc_use3(double %a, double %b, double %c) {227; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use3(228; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])229; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])230; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[AB]], [[CB]]231; CHECK-NEXT: call void @use(double [[AB]])232; CHECK-NEXT: call void @use(double [[CB]])233; CHECK-NEXT: ret double [[MUL]]234;235 %ab = call double @llvm.pow.f64(double %a, double %b)236 %cb = call double @llvm.pow.f64(double %c, double %b)237 %mul = fmul reassoc double %ab, %cb238 call void @use(double %ab)239 call void @use(double %cb)240 ret double %mul241}242 243define double @pow_ab_pow_ac(double %a, double %b, double %c) {244; CHECK-LABEL: @pow_ab_pow_ac(245; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])246; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])247; CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP2]], [[TMP1]]248; CHECK-NEXT: ret double [[MUL]]249;250 %1 = call double @llvm.pow.f64(double %a, double %b)251 %2 = call double @llvm.pow.f64(double %a, double %c)252 %mul = fmul double %2, %1253 ret double %mul254}255 256define double @pow_ab_x_pow_ac_reassoc(double %a, double %b, double %c) {257; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc(258; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[C:%.*]], [[B:%.*]]259; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])260; CHECK-NEXT: ret double [[MUL]]261;262 %1 = call double @llvm.pow.f64(double %a, double %b)263 %2 = call double @llvm.pow.f64(double %a, double %c)264 %mul = fmul reassoc double %2, %1265 ret double %mul266}267 268define double @pow_ab_reassoc(double %a, double %b) {269; CHECK-LABEL: @pow_ab_reassoc(270; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], [[B]]271; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])272; CHECK-NEXT: ret double [[MUL]]273;274 %1 = call double @llvm.pow.f64(double %a, double %b)275 %mul = fmul reassoc double %1, %1276 ret double %mul277}278 279define double @pow_ab_reassoc_extra_use(double %a, double %b) {280; CHECK-LABEL: @pow_ab_reassoc_extra_use(281; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])282; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP1]]283; CHECK-NEXT: call void @use(double [[TMP1]])284; CHECK-NEXT: ret double [[MUL]]285;286 %1 = call double @llvm.pow.f64(double %a, double %b)287 %mul = fmul reassoc double %1, %1288 call void @use(double %1)289 ret double %mul290}291 292define double @pow_ab_x_pow_ac_reassoc_extra_use(double %a, double %b, double %c) {293; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc_extra_use(294; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])295; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc double [[B]], [[C:%.*]]296; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[TMP2]])297; CHECK-NEXT: call void @use(double [[TMP1]])298; CHECK-NEXT: ret double [[MUL]]299;300 %1 = call double @llvm.pow.f64(double %a, double %b)301 %2 = call double @llvm.pow.f64(double %a, double %c)302 %mul = fmul reassoc double %1, %2303 call void @use(double %1)304 ret double %mul305}306 307define double @pow_ab_x_pow_ac_reassoc_multiple_uses(double %a, double %b, double %c) {308; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc_multiple_uses(309; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])310; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])311; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP2]]312; CHECK-NEXT: call void @use(double [[TMP1]])313; CHECK-NEXT: call void @use(double [[TMP2]])314; CHECK-NEXT: ret double [[MUL]]315;316 %1 = call double @llvm.pow.f64(double %a, double %b)317 %2 = call double @llvm.pow.f64(double %a, double %c)318 %mul = fmul reassoc double %1, %2319 call void @use(double %1)320 call void @use(double %2)321 ret double %mul322}323