223 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes=early-cse -earlycse-debug-hash | FileCheck %s3; RUN: opt < %s -S -passes='early-cse<memssa>' | FileCheck %s4 5; Test use of constrained floating point intrinsics with dynamic6; rounding mode. Dynamic rounding _must_ disable CSE since EarlyCSE7; will CSE across function calls and we cannot know if the rounding8; mode will be changed by any arbitrary function call.9 10define double @multiple_fadd(double %a, double %b) #0 {11; CHECK-LABEL: @multiple_fadd(12; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]]13; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]14; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]15; CHECK-NEXT: ret double [[TMP2]]16;17 %1 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #018 %2 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #019 %3 = call double @foo.f64(double %1, double %2) #020 ret double %221}22 23define double @multiple_fadd_split(double %a, double %b) #0 {24; CHECK-LABEL: @multiple_fadd_split(25; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]26; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]27; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]28; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]29; CHECK-NEXT: ret double [[TMP2]]30;31 %1 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #032 call void @arbitraryfunc() #033 %2 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #034 %3 = call double @foo.f64(double %1, double %2) #035 ret double %236}37 38define double @multiple_fsub(double %a, double %b) #0 {39; CHECK-LABEL: @multiple_fsub(40; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]41; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]42; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]43; CHECK-NEXT: ret double [[TMP2]]44;45 %1 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #046 %2 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #047 %3 = call double @foo.f64(double %1, double %2) #048 ret double %249}50 51define double @multiple_fsub_split(double %a, double %b) #0 {52; CHECK-LABEL: @multiple_fsub_split(53; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]54; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]55; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]56; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]57; CHECK-NEXT: ret double [[TMP2]]58;59 %1 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #060 call void @arbitraryfunc() #061 %2 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #062 %3 = call double @foo.f64(double %1, double %2) #063 ret double %264}65 66define double @multiple_fmul(double %a, double %b) #0 {67; CHECK-LABEL: @multiple_fmul(68; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]69; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]70; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]71; CHECK-NEXT: ret double [[TMP2]]72;73 %1 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #074 %2 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #075 %3 = call double @foo.f64(double %1, double %2) #076 ret double %277}78 79define double @multiple_fmul_split(double %a, double %b) #0 {80; CHECK-LABEL: @multiple_fmul_split(81; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]82; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]83; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]84; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]85; CHECK-NEXT: ret double [[TMP2]]86;87 %1 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #088 call void @arbitraryfunc() #089 %2 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #090 %3 = call double @foo.f64(double %1, double %2) #091 ret double %292}93 94define double @multiple_fdiv(double %a, double %b) #0 {95; CHECK-LABEL: @multiple_fdiv(96; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]97; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]98; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]99; CHECK-NEXT: ret double [[TMP2]]100;101 %1 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0102 %2 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0103 %3 = call double @foo.f64(double %1, double %2) #0104 ret double %2105}106 107define double @multiple_fdiv_split(double %a, double %b) #0 {108; CHECK-LABEL: @multiple_fdiv_split(109; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]110; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]111; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]112; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]113; CHECK-NEXT: ret double [[TMP2]]114;115 %1 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0116 call void @arbitraryfunc() #0117 %2 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0118 %3 = call double @foo.f64(double %1, double %2) #0119 ret double %2120}121 122define double @multiple_frem(double %a, double %b) #0 {123; CHECK-LABEL: @multiple_frem(124; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]125; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]126; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]127; CHECK-NEXT: ret double [[TMP2]]128;129 %1 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0130 %2 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0131 %3 = call double @foo.f64(double %1, double %2) #0132 ret double %2133}134 135define double @multiple_frem_split(double %a, double %b) #0 {136; CHECK-LABEL: @multiple_frem_split(137; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]138; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]139; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]140; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]141; CHECK-NEXT: ret double [[TMP2]]142;143 %1 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0144 call void @arbitraryfunc() #0145 %2 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0146 %3 = call double @foo.f64(double %1, double %2) #0147 ret double %2148}149 150define double @multiple_uitofp(i32 %a) #0 {151; CHECK-LABEL: @multiple_uitofp(152; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]153; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]154; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]155; CHECK-NEXT: ret double [[TMP2]]156;157 %1 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0158 %2 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0159 %3 = call double @foo.f64(double %1, double %1) #0160 ret double %2161}162 163define double @multiple_uitofp_split(i32 %a) #0 {164; CHECK-LABEL: @multiple_uitofp_split(165; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]166; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]167; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]168; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]169; CHECK-NEXT: ret double [[TMP2]]170;171 %1 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0172 call void @arbitraryfunc() #0173 %2 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0174 %3 = call double @foo.f64(double %1, double %1) #0175 ret double %2176}177 178define double @multiple_sitofp(i32 %a) #0 {179; CHECK-LABEL: @multiple_sitofp(180; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]181; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]182; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]183; CHECK-NEXT: ret double [[TMP2]]184;185 %1 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0186 %2 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0187 %3 = call double @foo.f64(double %1, double %1) #0188 ret double %2189}190 191define double @multiple_sitofp_split(i32 %a) #0 {192; CHECK-LABEL: @multiple_sitofp_split(193; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]194; CHECK-NEXT: call void @arbitraryfunc() #[[ATTR0]]195; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]196; CHECK-NEXT: [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]197; CHECK-NEXT: ret double [[TMP2]]198;199 %1 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0200 call void @arbitraryfunc() #0201 %2 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0202 %3 = call double @foo.f64(double %1, double %1) #0203 ret double %2204}205 206attributes #0 = { strictfp }207 208declare void @arbitraryfunc() #0209declare double @foo.f64(double, double) #0210declare i32 @bar.i32(i32, i32) #0211 212declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)213declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata)214declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)215declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)216declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata)217declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)218declare double @llvm.experimental.constrained.uitofp.f64.i32(i32, metadata, metadata)219declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)220declare double @llvm.experimental.constrained.sitofp.f64.i32(i32, metadata, metadata)221declare i1 @llvm.experimental.constrained.fcmp.i1.f64(double, double, metadata, metadata)222declare i1 @llvm.experimental.constrained.fcmps.i1.f64(double, double, metadata, metadata)223