1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; (X < +/-0.0) ? X : -X --> -fabs(X) 5; (X <= +/-0.0) ? X : -X --> -fabs(X) 6; One negative test with no fmf 7define double @select_noFMF_nfabs_lt(double %x) { 8; CHECK-LABEL: @select_noFMF_nfabs_lt( 9; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 10; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 11; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[NEGX]] 12; CHECK-NEXT: ret double [[SEL]] 13; 14 %cmp = fcmp olt double %x, 0.000000e+00 15 %negX = fneg double %x 16 %sel = select i1 %cmp, double %x, double %negX 17 ret double %sel 18} 19 20; One test where the neg has fmfs. 21define double @select_nsz_nfabs_lt_fmfProp(double %x) { 22; CHECK-LABEL: @select_nsz_nfabs_lt_fmfProp( 23; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) 24; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] 25; CHECK-NEXT: ret double [[SEL]] 26; 27 %cmp = fcmp olt double %x, 0.000000e+00 28 %negX = fneg fast double %x 29 %sel = select nsz i1 %cmp, double %x, double %negX 30 ret double %sel 31} 32 33define double @select_nsz_nnan_nfabs_lt_fmfProp(double %x) { 34; CHECK-LABEL: @select_nsz_nnan_nfabs_lt_fmfProp( 35; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) 36; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] 37; CHECK-NEXT: ret double [[SEL]] 38; 39 %cmp = fcmp olt double %x, 0.000000e+00 40 %negX = fneg fast double %x 41 %sel = select nsz nnan i1 %cmp, double %x, double %negX 42 ret double %sel 43} 44 45; Tests with various predicate types. 46 47; This is not fabs because that could produce a different signbit for a NAN input. 48; PR59279 49 50define double @select_nsz_nfabs_ult(double %x) { 51; CHECK-LABEL: @select_nsz_nfabs_ult( 52; CHECK-NEXT: [[CMP:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 53; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 54; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[X]], double [[NEGX]] 55; CHECK-NEXT: ret double [[SEL]] 56; 57 %cmp = fcmp ult double %x, 0.000000e+00 58 %negX = fneg double %x 59 %sel = select nsz i1 %cmp, double %x, double %negX 60 ret double %sel 61} 62 63define double @select_nsz_nnan_nfabs_ult(double %x) { 64; CHECK-LABEL: @select_nsz_nnan_nfabs_ult( 65; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 66; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 67; CHECK-NEXT: ret double [[SEL]] 68; 69 %cmp = fcmp ult double %x, 0.000000e+00 70 %negX = fneg double %x 71 %sel = select nsz nnan i1 %cmp, double %x, double %negX 72 ret double %sel 73} 74 75; This is not fabs because that could produce a different signbit for a NAN input. 76; PR59279 77 78define double @select_nsz_nfabs_ole(double %x) { 79; CHECK-LABEL: @select_nsz_nfabs_ole( 80; CHECK-NEXT: [[CMP:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 81; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 82; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[X]], double [[NEGX]] 83; CHECK-NEXT: ret double [[SEL]] 84; 85 %cmp = fcmp ole double %x, 0.000000e+00 86 %negX = fneg double %x 87 %sel = select nsz i1 %cmp, double %x, double %negX 88 ret double %sel 89} 90 91define double @select_nsz_nnan_nfabs_ole(double %x) { 92; CHECK-LABEL: @select_nsz_nnan_nfabs_ole( 93; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 94; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 95; CHECK-NEXT: ret double [[SEL]] 96; 97 %cmp = fcmp ole double %x, 0.000000e+00 98 %negX = fneg double %x 99 %sel = select nsz nnan i1 %cmp, double %x, double %negX 100 ret double %sel 101} 102 103; This is not fabs because that could produce a different signbit for a NAN input. 104; PR59279 105 106define double @select_nsz_nfabs_ule(double %x) { 107; CHECK-LABEL: @select_nsz_nfabs_ule( 108; CHECK-NEXT: [[CMP:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 109; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 110; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[X]], double [[NEGX]] 111; CHECK-NEXT: ret double [[SEL]] 112; 113 %cmp = fcmp ule double %x, 0.000000e+00 114 %negX = fneg double %x 115 %sel = select nsz i1 %cmp, double %x, double %negX 116 ret double %sel 117} 118 119define double @select_nsz_nnan_nfabs_ule(double %x) { 120; CHECK-LABEL: @select_nsz_nnan_nfabs_ule( 121; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 122; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 123; CHECK-NEXT: ret double [[SEL]] 124; 125 %cmp = fcmp ule double %x, 0.000000e+00 126 %negX = fneg double %x 127 %sel = select nsz nnan i1 %cmp, double %x, double %negX 128 ret double %sel 129} 130 131; (X > +/-0.0) ? -X : X --> -fabs(X) 132; (X >= +/-0.0) ? -X : X --> -fabs(X) 133; One negative test with no fmf 134define double @select_noFMF_nfabs_gt(double %x) { 135; CHECK-LABEL: @select_noFMF_nfabs_gt( 136; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[X:%.*]], 0.000000e+00 137; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 138; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], double [[NEGX]], double [[X]] 139; CHECK-NEXT: ret double [[SEL]] 140; 141 %cmp = fcmp ogt double %x, 0.000000e+00 142 %negX = fneg double %x 143 %sel = select i1 %cmp, double %negX, double %x 144 ret double %sel 145} 146 147; One test where the neg has fmfs. 148define double @select_nsz_nfabs_gt_fmfProp(double %x) { 149; CHECK-LABEL: @select_nsz_nfabs_gt_fmfProp( 150; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) 151; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] 152; CHECK-NEXT: ret double [[SEL]] 153; 154 %cmp = fcmp ogt double %x, 0.000000e+00 155 %negX = fneg fast double %x 156 %sel = select nsz i1 %cmp, double %negX, double %x 157 ret double %sel 158} 159 160define double @select_nsz_nnan_nfabs_gt_fmfProp(double %x) { 161; CHECK-LABEL: @select_nsz_nnan_nfabs_gt_fmfProp( 162; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) 163; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] 164; CHECK-NEXT: ret double [[SEL]] 165; 166 %cmp = fcmp ogt double %x, 0.000000e+00 167 %negX = fneg fast double %x 168 %sel = select nsz nnan i1 %cmp, double %negX, double %x 169 ret double %sel 170} 171 172; This is not fabs because that could produce a different signbit for a NAN input. 173; PR59279 174 175define double @select_nsz_nfabs_ogt(double %x) { 176; CHECK-LABEL: @select_nsz_nfabs_ogt( 177; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[X:%.*]], 0.000000e+00 178; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 179; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[NEGX]], double [[X]] 180; CHECK-NEXT: ret double [[SEL]] 181; 182 %cmp = fcmp ogt double %x, 0.000000e+00 183 %negX = fneg double %x 184 %sel = select nsz i1 %cmp, double %negX, double %x 185 ret double %sel 186} 187 188; Tests with various predicate types. 189 190define double @select_nsz_nnan_nfabs_ogt(double %x) { 191; CHECK-LABEL: @select_nsz_nnan_nfabs_ogt( 192; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 193; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 194; CHECK-NEXT: ret double [[SEL]] 195; 196 %cmp = fcmp ogt double %x, 0.000000e+00 197 %negX = fneg double %x 198 %sel = select nsz nnan i1 %cmp, double %negX, double %x 199 ret double %sel 200} 201 202; This is not fabs because that could produce a different signbit for a NAN input. 203; PR59279 204 205define double @select_nsz_nfabs_ugt(double %x) { 206; CHECK-LABEL: @select_nsz_nfabs_ugt( 207; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt double [[X:%.*]], 0.000000e+00 208; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 209; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[NEGX]], double [[X]] 210; CHECK-NEXT: ret double [[SEL]] 211; 212 %cmp = fcmp ugt double %x, 0.000000e+00 213 %negX = fneg double %x 214 %sel = select nsz i1 %cmp, double %negX, double %x 215 ret double %sel 216} 217 218define double @select_nsz_nnan_nfabs_ugt(double %x) { 219; CHECK-LABEL: @select_nsz_nnan_nfabs_ugt( 220; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 221; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 222; CHECK-NEXT: ret double [[SEL]] 223; 224 %cmp = fcmp ugt double %x, 0.000000e+00 225 %negX = fneg double %x 226 %sel = select nsz nnan i1 %cmp, double %negX, double %x 227 ret double %sel 228} 229 230; This is not fabs because that could produce a different signbit for a NAN input. 231; PR59279 232 233define double @select_nsz_nfabs_oge(double %x) { 234; CHECK-LABEL: @select_nsz_nfabs_oge( 235; CHECK-NEXT: [[CMP:%.*]] = fcmp oge double [[X:%.*]], 0.000000e+00 236; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 237; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[NEGX]], double [[X]] 238; CHECK-NEXT: ret double [[SEL]] 239; 240 %cmp = fcmp oge double %x, 0.000000e+00 241 %negX = fneg double %x 242 %sel = select nsz i1 %cmp, double %negX, double %x 243 ret double %sel 244} 245 246define double @select_nsz_nnan_nfabs_oge(double %x) { 247; CHECK-LABEL: @select_nsz_nnan_nfabs_oge( 248; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 249; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 250; CHECK-NEXT: ret double [[SEL]] 251; 252 %cmp = fcmp oge double %x, 0.000000e+00 253 %negX = fneg double %x 254 %sel = select nsz nnan i1 %cmp, double %negX, double %x 255 ret double %sel 256} 257 258; This is not fabs because that could produce a different signbit for a NAN input. 259; PR59279 260 261define double @select_nsz_nfabs_uge(double %x) { 262; CHECK-LABEL: @select_nsz_nfabs_uge( 263; CHECK-NEXT: [[CMP:%.*]] = fcmp uge double [[X:%.*]], 0.000000e+00 264; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 265; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[NEGX]], double [[X]] 266; CHECK-NEXT: ret double [[SEL]] 267; 268 %cmp = fcmp uge double %x, 0.000000e+00 269 %negX = fneg double %x 270 %sel = select nsz i1 %cmp, double %negX, double %x 271 ret double %sel 272} 273 274define double @select_nsz_nnan_nfabs_uge(double %x) { 275; CHECK-LABEL: @select_nsz_nnan_nfabs_uge( 276; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 277; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] 278; CHECK-NEXT: ret double [[SEL]] 279; 280 %cmp = fcmp uge double %x, 0.000000e+00 281 %negX = fneg double %x 282 %sel = select nsz nnan i1 %cmp, double %negX, double %x 283 ret double %sel 284} 285 286; (X < +/-0.0) ? X : (0.0 - X) --> (0.0 - fabs(X)) 287; One negative test with <=. 288define double @select_noFMF_fsubfabs_le(double %x) { 289; CHECK-LABEL: @select_noFMF_fsubfabs_le( 290; CHECK-NEXT: [[CMP:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 291; CHECK-NEXT: [[SUB:%.*]] = fsub double 0.000000e+00, [[X]] 292; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], double [[X]], double [[SUB]] 293; CHECK-NEXT: ret double [[RETVAL_0]] 294; 295 %cmp = fcmp ole double %x, 0.000000e+00 296 %sub = fsub double 0.000000e+00, %x 297 %retval.0 = select i1 %cmp, double %x, double %sub 298 ret double %retval.0 299} 300 301define double @select_noFMF_fsubfabs_olt(double %x) { 302; CHECK-LABEL: @select_noFMF_fsubfabs_olt( 303; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 304; CHECK-NEXT: [[SUB:%.*]] = fsub double 0.000000e+00, [[X]] 305; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], double [[X]], double [[SUB]] 306; CHECK-NEXT: ret double [[RETVAL_0]] 307; 308 %cmp = fcmp olt double %x, 0.000000e+00 309 %sub = fsub double 0.000000e+00, %x 310 %retval.0 = select i1 %cmp, double %x, double %sub 311 ret double %retval.0 312} 313 314define double @select_noFMF_fsubfabs_ult(double %x) { 315; CHECK-LABEL: @select_noFMF_fsubfabs_ult( 316; CHECK-NEXT: [[CMP:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 317; CHECK-NEXT: [[SUB:%.*]] = fsub double 0.000000e+00, [[X]] 318; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], double [[X]], double [[SUB]] 319; CHECK-NEXT: ret double [[RETVAL_0]] 320; 321 %cmp = fcmp ult double %x, 0.000000e+00 322 %sub = fsub double 0.000000e+00, %x 323 %retval.0 = select i1 %cmp, double %x, double %sub 324 ret double %retval.0 325} 326 327 328; With nsz: 329; (X < +/-0.0) ? X : -X --> -fabs(X) 330define double @select_nsz_fnegfabs_olt(double %x) { 331; CHECK-LABEL: @select_nsz_fnegfabs_olt( 332; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 333; CHECK-NEXT: [[NEGX:%.*]] = fneg nsz double [[X]] 334; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], double [[X]], double [[NEGX]] 335; CHECK-NEXT: ret double [[RETVAL_0]] 336; 337 %cmp = fcmp olt double %x, 0.000000e+00 338 %negX = fneg nsz double %x 339 %retval.0 = select i1 %cmp, double %x, double %negX 340 ret double %retval.0 341} 342 343define double @select_nsz_fnegfabs_ult(double %x) { 344; CHECK-LABEL: @select_nsz_fnegfabs_ult( 345; CHECK-NEXT: [[CMP:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 346; CHECK-NEXT: [[NEGX:%.*]] = fneg nsz double [[X]] 347; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], double [[X]], double [[NEGX]] 348; CHECK-NEXT: ret double [[RETVAL_0]] 349; 350 %cmp = fcmp ult double %x, 0.000000e+00 351 %negX = fneg nsz double %x 352 %retval.0 = select i1 %cmp, double %x, double %negX 353 ret double %retval.0 354} 355