1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare double @llvm.exp2.f64(double) nounwind readnone speculatable 5declare void @use(double) 6 7; exp2(a) * exp2(b) no reassoc flags 8define double @exp2_a_exp2_b(double %a, double %b) { 9; CHECK-LABEL: @exp2_a_exp2_b( 10; CHECK-NEXT: [[T:%.*]] = call double @llvm.exp2.f64(double [[A:%.*]]) 11; CHECK-NEXT: [[T1:%.*]] = call double @llvm.exp2.f64(double [[B:%.*]]) 12; CHECK-NEXT: [[MUL:%.*]] = fmul double [[T]], [[T1]] 13; CHECK-NEXT: ret double [[MUL]] 14; 15 %t = call double @llvm.exp2.f64(double %a) 16 %t1 = call double @llvm.exp2.f64(double %b) 17 %mul = fmul double %t, %t1 18 ret double %mul 19} 20 21; exp2(a) * exp2(b) reassoc, multiple uses 22define double @exp2_a_exp2_b_multiple_uses(double %a, double %b) { 23; CHECK-LABEL: @exp2_a_exp2_b_multiple_uses( 24; CHECK-NEXT: [[T1:%.*]] = call double @llvm.exp2.f64(double [[B:%.*]]) 25; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[B]] 26; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP1]]) 27; CHECK-NEXT: call void @use(double [[T1]]) 28; CHECK-NEXT: ret double [[MUL]] 29; 30 %t = call double @llvm.exp2.f64(double %a) 31 %t1 = call double @llvm.exp2.f64(double %b) 32 %mul = fmul reassoc double %t, %t1 33 call void @use(double %t1) 34 ret double %mul 35} 36 37define double @exp2_a_a(double %a) { 38; CHECK-LABEL: @exp2_a_a( 39; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[A]] 40; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP1]]) 41; CHECK-NEXT: ret double [[M]] 42; 43 %t = call double @llvm.exp2.f64(double %a) 44 %m = fmul reassoc double %t, %t 45 ret double %m 46} 47 48; exp2(a) * exp2(b) reassoc, both with multiple uses 49define double @exp2_a_exp2_b_multiple_uses_both(double %a, double %b) { 50; CHECK-LABEL: @exp2_a_exp2_b_multiple_uses_both( 51; CHECK-NEXT: [[T:%.*]] = call double @llvm.exp2.f64(double [[A:%.*]]) 52; CHECK-NEXT: [[T1:%.*]] = call double @llvm.exp2.f64(double [[B:%.*]]) 53; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[T]], [[T1]] 54; CHECK-NEXT: call void @use(double [[T]]) 55; CHECK-NEXT: call void @use(double [[T1]]) 56; CHECK-NEXT: ret double [[MUL]] 57; 58 %t = call double @llvm.exp2.f64(double %a) 59 %t1 = call double @llvm.exp2.f64(double %b) 60 %mul = fmul reassoc double %t, %t1 61 call void @use(double %t) 62 call void @use(double %t1) 63 ret double %mul 64} 65 66; exp2(a) * exp2(b) => exp2(a+b) with reassoc 67define double @exp2_a_exp2_b_reassoc(double %a, double %b) { 68; CHECK-LABEL: @exp2_a_exp2_b_reassoc( 69; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[B:%.*]] 70; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP1]]) 71; CHECK-NEXT: ret double [[MUL]] 72; 73 %t = call double @llvm.exp2.f64(double %a) 74 %t1 = call double @llvm.exp2.f64(double %b) 75 %mul = fmul reassoc double %t, %t1 76 ret double %mul 77} 78 79; exp2(a) * exp2(b) * exp2(c) * exp2(d) => exp2(a+b+c+d) with reassoc 80define double @exp2_a_exp2_b_exp2_c_exp2_d(double %a, double %b, double %c, double %d) { 81; CHECK-LABEL: @exp2_a_exp2_b_exp2_c_exp2_d( 82; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[B:%.*]] 83; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc double [[TMP1]], [[C:%.*]] 84; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc double [[TMP2]], [[D:%.*]] 85; CHECK-NEXT: [[MUL2:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP3]]) 86; CHECK-NEXT: ret double [[MUL2]] 87; 88 %t = call double @llvm.exp2.f64(double %a) 89 %t1 = call double @llvm.exp2.f64(double %b) 90 %mul = fmul reassoc double %t, %t1 91 %t2 = call double @llvm.exp2.f64(double %c) 92 %mul1 = fmul reassoc double %mul, %t2 93 %t3 = call double @llvm.exp2.f64(double %d) 94 %mul2 = fmul reassoc double %mul1, %t3 95 ret double %mul2 96} 97