1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4; 5; Check constrained detection of cases where negative zero is impossible: 6; 7 8define float @nonneg_u_defaultenv(i32 %a) #0 { 9; CHECK-LABEL: @nonneg_u_defaultenv( 10; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]] 11; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 12; CHECK-NEXT: ret float [[SQRA]] 13; 14 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 15 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 16 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 17 ret float %sub 18} 19 20define float @nonneg_s_defaultenv(i32 %a) #0 { 21; CHECK-LABEL: @nonneg_s_defaultenv( 22; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 23; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] 24; CHECK-NEXT: ret float [[SQRA]] 25; 26 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 27 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 28 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 29 ret float %sub 30} 31 32define float @nonneg_u_maytrap(i32 %a) #0 { 33; CHECK-LABEL: @nonneg_u_maytrap( 34; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] 35; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] 36; CHECK-NEXT: ret float [[SQRA]] 37; 38 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 39 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 40 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 41 ret float %sub 42} 43 44define float @nonneg_s_maytrap(i32 %a) #0 { 45; CHECK-LABEL: @nonneg_s_maytrap( 46; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] 47; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]] 48; CHECK-NEXT: ret float [[SQRA]] 49; 50 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 51 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 52 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0 53 ret float %sub 54} 55 56; NOTE: The fsub instruction is expected to remain, but the result isn't used. 57define float @nonneg_u_ebstrict(i32 %a) #0 { 58; CHECK-LABEL: @nonneg_u_ebstrict( 59; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 60; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 61; CHECK-NEXT: [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[SQRA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 62; CHECK-NEXT: ret float [[SQRA]] 63; 64 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 65 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 66 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 67 ret float %sub 68} 69 70; NOTE: The fsub instruction is expected to remain, but the result isn't used. 71define float @nonneg_s_ebstrict(i32 %a) #0 { 72; CHECK-LABEL: @nonneg_s_ebstrict( 73; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 74; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 75; CHECK-NEXT: [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[SQRA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] 76; CHECK-NEXT: ret float [[SQRA]] 77; 78 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 79 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 80 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 81 ret float %sub 82} 83 84; Test all the rounding modes. Rounding mode and exception handling 85; shouldn't matter. 86 87define float @nonneg_u_downward(i32 %a) #0 { 88; CHECK-LABEL: @nonneg_u_downward( 89; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.downward", metadata !"fpexcept.ignore") #[[ATTR0]] 90; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.downward", metadata !"fpexcept.ignore") #[[ATTR0]] 91; CHECK-NEXT: ret float [[SQRA]] 92; 93 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.downward", metadata !"fpexcept.ignore") #0 94 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.downward", metadata !"fpexcept.ignore") #0 95 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.downward", metadata !"fpexcept.ignore") #0 96 ret float %sub 97} 98 99define float @nonneg_s_downward(i32 %a) #0 { 100; CHECK-LABEL: @nonneg_s_downward( 101; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.downward", metadata !"fpexcept.ignore") #[[ATTR0]] 102; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.downward", metadata !"fpexcept.ignore") #[[ATTR0]] 103; CHECK-NEXT: ret float [[SQRA]] 104; 105 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.downward", metadata !"fpexcept.ignore") #0 106 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.downward", metadata !"fpexcept.ignore") #0 107 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.downward", metadata !"fpexcept.ignore") #0 108 ret float %sub 109} 110 111define float @nonneg_u_upward(i32 %a) #0 { 112; CHECK-LABEL: @nonneg_u_upward( 113; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] 114; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] 115; CHECK-NEXT: ret float [[SQRA]] 116; 117 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.upward", metadata !"fpexcept.ignore") #0 118 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.upward", metadata !"fpexcept.ignore") #0 119 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.upward", metadata !"fpexcept.ignore") #0 120 ret float %sub 121} 122 123define float @nonneg_s_upward(i32 %a) #0 { 124; CHECK-LABEL: @nonneg_s_upward( 125; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] 126; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] 127; CHECK-NEXT: ret float [[SQRA]] 128; 129 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.upward", metadata !"fpexcept.ignore") #0 130 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.upward", metadata !"fpexcept.ignore") #0 131 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.upward", metadata !"fpexcept.ignore") #0 132 ret float %sub 133} 134 135define float @nonneg_u_towardzero(i32 %a) #0 { 136; CHECK-LABEL: @nonneg_u_towardzero( 137; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] 138; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] 139; CHECK-NEXT: ret float [[SQRA]] 140; 141 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 142 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 143 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 144 ret float %sub 145} 146 147define float @nonneg_s_towardzero(i32 %a) #0 { 148; CHECK-LABEL: @nonneg_s_towardzero( 149; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] 150; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.towardzero", metadata !"fpexcept.ignore") #[[ATTR0]] 151; CHECK-NEXT: ret float [[SQRA]] 152; 153 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 154 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 155 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.towardzero", metadata !"fpexcept.ignore") #0 156 ret float %sub 157} 158 159define float @nonneg_u_tonearestaway(i32 %a) #0 { 160; CHECK-LABEL: @nonneg_u_tonearestaway( 161; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #[[ATTR0]] 162; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #[[ATTR0]] 163; CHECK-NEXT: ret float [[SQRA]] 164; 165 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 166 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 167 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 168 ret float %sub 169} 170 171define float @nonneg_s_tonearestaway(i32 %a) #0 { 172; CHECK-LABEL: @nonneg_s_tonearestaway( 173; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #[[ATTR0]] 174; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #[[ATTR0]] 175; CHECK-NEXT: ret float [[SQRA]] 176; 177 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 178 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 179 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") #0 180 ret float %sub 181} 182 183define float @nonneg_u_dynamic(i32 %a) #0 { 184; CHECK-LABEL: @nonneg_u_dynamic( 185; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]] 186; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]] 187; CHECK-NEXT: ret float [[SQRA]] 188; 189 %fpa = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 190 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 191 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 192 ret float %sub 193} 194 195define float @nonneg_s_dynamic(i32 %a) #0 { 196; CHECK-LABEL: @nonneg_s_dynamic( 197; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]] 198; CHECK-NEXT: [[SQRA:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[FPA]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]] 199; CHECK-NEXT: ret float [[SQRA]] 200; 201 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 202 %sqra = call float @llvm.experimental.constrained.sqrt.f32(float %fpa, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 203 %sub = call float @llvm.experimental.constrained.fsub.f32(float %sqra, float -0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 204 ret float %sub 205} 206 207declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata) #0 208declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0 209 210declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata) #0 211declare float @llvm.experimental.constrained.uitofp.f32.i32(i32, metadata, metadata) #0 212 213attributes #0 = { strictfp } 214