1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4define float @fdiv_constant_fold() #0 { 5; CHECK-LABEL: @fdiv_constant_fold( 6; CHECK-NEXT: ret float 1.500000e+00 7; 8 %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 9 10 ret float %f 11} 12 13define float @fdiv_constant_fold_strict() #0 { 14; CHECK-LABEL: @fdiv_constant_fold_strict( 15; CHECK-NEXT: [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]] 16; CHECK-NEXT: ret float 1.500000e+00 17; 18 %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 19 20 ret float %f 21} 22 23define float @fdiv_constant_fold_strict2() #0 { 24; CHECK-LABEL: @fdiv_constant_fold_strict2( 25; CHECK-NEXT: [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 2.000000e+00, float 3.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 26; CHECK-NEXT: ret float [[F]] 27; 28 %f = call float @llvm.experimental.constrained.fdiv.f32(float 2.0, float 3.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 29 30 ret float %f 31} 32 33define float @frem_constant_fold() #0 { 34; CHECK-LABEL: @frem_constant_fold( 35; CHECK-NEXT: ret float 1.000000e+00 36; 37 %f = call float @llvm.experimental.constrained.frem.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 38 ret float %f 39} 40 41define float @frem_constant_fold_strict() #0 { 42; CHECK-LABEL: @frem_constant_fold_strict( 43; CHECK-NEXT: [[F:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 44; CHECK-NEXT: ret float 1.000000e+00 45; 46 %f = call float @llvm.experimental.constrained.frem.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 47 ret float %f 48} 49 50define double @fmul_fdiv_common_operand(double %x, double %y) #0 { 51; CHECK-LABEL: @fmul_fdiv_common_operand( 52; CHECK-NEXT: [[M:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 53; CHECK-NEXT: [[D:%.*]] = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 54; CHECK-NEXT: ret double [[D]] 55; 56 %m = call double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 57 %d = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 58 ret double %d 59} 60 61; Negative test - the fdiv must be reassociative and not allow NaNs. 62 63define double @fmul_fdiv_common_operand_too_strict(double %x, double %y) #0 { 64; CHECK-LABEL: @fmul_fdiv_common_operand_too_strict( 65; CHECK-NEXT: [[M:%.*]] = call fast double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 66; CHECK-NEXT: [[D:%.*]] = call reassoc double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 67; CHECK-NEXT: ret double [[D]] 68; 69 %m = call fast double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 70 %d = call reassoc double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 71 ret double %d 72} 73 74; Commute the fmul operands. Use a vector type to verify that works too. 75 76define <2 x float> @fmul_fdiv_common_operand_commute_vec(<2 x float> %x, <2 x float> %y) #0 { 77; CHECK-LABEL: @fmul_fdiv_common_operand_commute_vec( 78; CHECK-NEXT: [[M:%.*]] = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> [[Y:%.*]], <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 79; CHECK-NEXT: [[D:%.*]] = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> [[M]], <2 x float> [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 80; CHECK-NEXT: ret <2 x float> [[D]] 81; 82 %m = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> %y, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 83 %d = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> %m, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 84 ret <2 x float> %d 85} 86 87declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0 88declare <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 89 90declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0 91declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) #0 92declare <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 93 94declare float @llvm.experimental.constrained.frem.f32(float, float, metadata, metadata) #0 95 96attributes #0 = { strictfp } 97 98