203 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -mtriple armv7-- -mattr=+vfp4 %s -o - | FileCheck %s3 4 5; Div whose result is unused should be removed unless we have strict exceptions6 7define void @unused_div(float %x, float %y) {8; CHECK-LABEL: unused_div:9; CHECK: @ %bb.0: @ %entry10; CHECK-NEXT: bx lr11entry:12 %add = fdiv float %x, %y13 ret void14}15 16define void @unused_div_fpexcept_strict(float %x, float %y) #0 {17; CHECK-LABEL: unused_div_fpexcept_strict:18; CHECK: @ %bb.0: @ %entry19; CHECK-NEXT: vmov s0, r120; CHECK-NEXT: vmov s2, r021; CHECK-NEXT: vdiv.f32 s0, s2, s022; CHECK-NEXT: bx lr23entry:24 %add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #025 ret void26}27 28define void @unused_div_round_dynamic(float %x, float %y) #0 {29; CHECK-LABEL: unused_div_round_dynamic:30; CHECK: @ %bb.0: @ %entry31; CHECK-NEXT: bx lr32entry:33 %add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #034 ret void35}36 37 38; Machine CSE should eliminate the second add unless we have strict exceptions39 40define float @add_twice(float %x, float %y, i32 %n) {41; CHECK-LABEL: add_twice:42; CHECK: @ %bb.0: @ %entry43; CHECK-NEXT: vmov s0, r144; CHECK-NEXT: cmp r2, #045; CHECK-NEXT: vmov s2, r046; CHECK-NEXT: vadd.f32 s0, s2, s047; CHECK-NEXT: vmul.f32 s2, s0, s048; CHECK-NEXT: vmoveq.f32 s2, s049; CHECK-NEXT: vmov r0, s250; CHECK-NEXT: bx lr51entry:52 %add = fadd float %x, %y53 %tobool.not = icmp eq i32 %n, 054 br i1 %tobool.not, label %if.end, label %if.then55 56if.then:57 %add1 = fadd float %x, %y58 %mul = fmul float %add, %add159 br label %if.end60 61if.end:62 %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]63 ret float %a.064}65 66define float @add_twice_fpexcept_strict(float %x, float %y, i32 %n) #0 {67; CHECK-LABEL: add_twice_fpexcept_strict:68; CHECK: @ %bb.0: @ %entry69; CHECK-NEXT: vmov s2, r170; CHECK-NEXT: cmp r2, #071; CHECK-NEXT: vmov s4, r072; CHECK-NEXT: vadd.f32 s0, s4, s273; CHECK-NEXT: vaddne.f32 s2, s4, s274; CHECK-NEXT: vmulne.f32 s0, s0, s275; CHECK-NEXT: vmov r0, s076; CHECK-NEXT: bx lr77entry:78 %add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #079 %tobool.not = icmp eq i32 %n, 080 br i1 %tobool.not, label %if.end, label %if.then81 82if.then:83 %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #084 %mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.tonearest", metadata !"fpexcept.strict") #085 br label %if.end86 87if.end:88 %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]89 ret float %a.090}91 92define float @add_twice_round_dynamic(float %x, float %y, i32 %n) #0 {93; CHECK-LABEL: add_twice_round_dynamic:94; CHECK: @ %bb.0: @ %entry95; CHECK-NEXT: vmov s0, r196; CHECK-NEXT: cmp r2, #097; CHECK-NEXT: vmov s2, r098; CHECK-NEXT: vadd.f32 s0, s2, s099; CHECK-NEXT: vmulne.f32 s0, s0, s0100; CHECK-NEXT: vmov r0, s0101; CHECK-NEXT: bx lr102entry:103 %add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0104 %tobool.not = icmp eq i32 %n, 0105 br i1 %tobool.not, label %if.end, label %if.then106 107if.then:108 %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0109 %mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0110 br label %if.end111 112if.end:113 %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]114 ret float %a.0115}116 117; Two adds separated by llvm.set.rounding should be preserved when rounding is118; dynamic (as they may give different results) or when we have strict exceptions119; (the llvm.set.rounding is irrelevant, but both could trap).120 121define float @set_rounding(float %x, float %y) {122; CHECK-LABEL: set_rounding:123; CHECK: @ %bb.0: @ %entry124; CHECK-NEXT: vmrs r2, fpscr125; CHECK-NEXT: vmov s2, r0126; CHECK-NEXT: vmov s0, r1127; CHECK-NEXT: vadd.f32 s0, s2, s0128; CHECK-NEXT: vsub.f32 s0, s0, s0129; CHECK-NEXT: orr r0, r2, #12582912130; CHECK-NEXT: vmsr fpscr, r0131; CHECK-NEXT: vmov r0, s0132; CHECK-NEXT: vmrs r1, fpscr133; CHECK-NEXT: bic r1, r1, #12582912134; CHECK-NEXT: vmsr fpscr, r1135; CHECK-NEXT: bx lr136entry:137 %add1 = fadd float %x, %y138 call void @llvm.set.rounding(i32 0)139 %add2 = fadd float %x, %y140 call void @llvm.set.rounding(i32 1)141 %sub = fsub float %add1, %add2142 ret float %sub143}144 145define float @set_rounding_fpexcept_strict(float %x, float %y) #0 {146; CHECK-LABEL: set_rounding_fpexcept_strict:147; CHECK: @ %bb.0: @ %entry148; CHECK-NEXT: vmov s0, r1149; CHECK-NEXT: vmov s2, r0150; CHECK-NEXT: vadd.f32 s4, s2, s0151; CHECK-NEXT: vmrs r0, fpscr152; CHECK-NEXT: orr r0, r0, #12582912153; CHECK-NEXT: vmsr fpscr, r0154; CHECK-NEXT: vadd.f32 s0, s2, s0155; CHECK-NEXT: vmrs r0, fpscr156; CHECK-NEXT: bic r0, r0, #12582912157; CHECK-NEXT: vmsr fpscr, r0158; CHECK-NEXT: vsub.f32 s0, s4, s0159; CHECK-NEXT: vmov r0, s0160; CHECK-NEXT: bx lr161entry:162 %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0163 call void @llvm.set.rounding(i32 0) #0164 %add2 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0165 call void @llvm.set.rounding(i32 1) #0166 %sub = call float @llvm.experimental.constrained.fsub.f32(float %add1, float %add2, metadata !"round.tonearest", metadata !"fpexcept.strict") #0167 ret float %sub168}169 170define float @set_rounding_round_dynamic(float %x, float %y) #0 {171; CHECK-LABEL: set_rounding_round_dynamic:172; CHECK: @ %bb.0: @ %entry173; CHECK-NEXT: vmov s2, r0174; CHECK-NEXT: vmrs r0, fpscr175; CHECK-NEXT: vmov s0, r1176; CHECK-NEXT: vadd.f32 s4, s2, s0177; CHECK-NEXT: orr r0, r0, #12582912178; CHECK-NEXT: vmsr fpscr, r0179; CHECK-NEXT: vmrs r0, fpscr180; CHECK-NEXT: vadd.f32 s0, s2, s0181; CHECK-NEXT: bic r0, r0, #12582912182; CHECK-NEXT: vmsr fpscr, r0183; CHECK-NEXT: vsub.f32 s0, s4, s0184; CHECK-NEXT: vmov r0, s0185; CHECK-NEXT: bx lr186entry:187 %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0188 call void @llvm.set.rounding(i32 0) #0189 %add2 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0190 call void @llvm.set.rounding(i32 1) #0191 %sub = call float @llvm.experimental.constrained.fsub.f32(float %add1, float %add2, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0192 ret float %sub193}194 195declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)196declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)197declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata)198declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata)199declare i32 @llvm.get.rounding()200declare void @llvm.set.rounding(i32)201 202attributes #0 = { strictfp }203