github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/gc/testdata/arith_ssa.go (about) 1 // run 2 3 // Copyright 2015 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Tests arithmetic expressions 8 9 package main 10 11 import "fmt" 12 13 const ( 14 y = 0x0fffFFFF 15 ) 16 17 //go:noinline 18 func lshNop1(x uint64) uint64 { 19 // two outer shifts should be removed 20 return (((x << 5) >> 2) << 2) 21 } 22 23 //go:noinline 24 func lshNop2(x uint64) uint64 { 25 return (((x << 5) >> 2) << 3) 26 } 27 28 //go:noinline 29 func lshNop3(x uint64) uint64 { 30 return (((x << 5) >> 2) << 6) 31 } 32 33 //go:noinline 34 func lshNotNop(x uint64) uint64 { 35 // outer shift can't be removed 36 return (((x << 5) >> 2) << 1) 37 } 38 39 //go:noinline 40 func rshNop1(x uint64) uint64 { 41 return (((x >> 5) << 2) >> 2) 42 } 43 44 //go:noinline 45 func rshNop2(x uint64) uint64 { 46 return (((x >> 5) << 2) >> 3) 47 } 48 49 //go:noinline 50 func rshNop3(x uint64) uint64 { 51 return (((x >> 5) << 2) >> 6) 52 } 53 54 //go:noinline 55 func rshNotNop(x uint64) uint64 { 56 return (((x >> 5) << 2) >> 1) 57 } 58 59 func testShiftRemoval() { 60 allSet := ^uint64(0) 61 if want, got := uint64(0x7ffffffffffffff), rshNop1(allSet); want != got { 62 println("testShiftRemoval rshNop1 failed, wanted", want, "got", got) 63 failed = true 64 } 65 if want, got := uint64(0x3ffffffffffffff), rshNop2(allSet); want != got { 66 println("testShiftRemoval rshNop2 failed, wanted", want, "got", got) 67 failed = true 68 } 69 if want, got := uint64(0x7fffffffffffff), rshNop3(allSet); want != got { 70 println("testShiftRemoval rshNop3 failed, wanted", want, "got", got) 71 failed = true 72 } 73 if want, got := uint64(0xffffffffffffffe), rshNotNop(allSet); want != got { 74 println("testShiftRemoval rshNotNop failed, wanted", want, "got", got) 75 failed = true 76 } 77 if want, got := uint64(0xffffffffffffffe0), lshNop1(allSet); want != got { 78 println("testShiftRemoval lshNop1 failed, wanted", want, "got", got) 79 failed = true 80 } 81 if want, got := uint64(0xffffffffffffffc0), lshNop2(allSet); want != got { 82 println("testShiftRemoval lshNop2 failed, wanted", want, "got", got) 83 failed = true 84 } 85 if want, got := uint64(0xfffffffffffffe00), lshNop3(allSet); want != got { 86 println("testShiftRemoval lshNop3 failed, wanted", want, "got", got) 87 failed = true 88 } 89 if want, got := uint64(0x7ffffffffffffff0), lshNotNop(allSet); want != got { 90 println("testShiftRemoval lshNotNop failed, wanted", want, "got", got) 91 failed = true 92 } 93 } 94 95 //go:noinline 96 func parseLE64(b []byte) uint64 { 97 // skip the first two bytes, and parse the remaining 8 as a uint64 98 return uint64(b[2]) | uint64(b[3])<<8 | uint64(b[4])<<16 | uint64(b[5])<<24 | 99 uint64(b[6])<<32 | uint64(b[7])<<40 | uint64(b[8])<<48 | uint64(b[9])<<56 100 } 101 102 //go:noinline 103 func parseLE32(b []byte) uint32 { 104 return uint32(b[2]) | uint32(b[3])<<8 | uint32(b[4])<<16 | uint32(b[5])<<24 105 } 106 107 //go:noinline 108 func parseLE16(b []byte) uint16 { 109 return uint16(b[2]) | uint16(b[3])<<8 110 } 111 112 // testLoadCombine tests for issue #14694 where load combining didn't respect the pointer offset. 113 func testLoadCombine() { 114 testData := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09} 115 if want, got := uint64(0x0908070605040302), parseLE64(testData); want != got { 116 println("testLoadCombine failed, wanted", want, "got", got) 117 failed = true 118 } 119 if want, got := uint32(0x05040302), parseLE32(testData); want != got { 120 println("testLoadCombine failed, wanted", want, "got", got) 121 failed = true 122 } 123 if want, got := uint16(0x0302), parseLE16(testData); want != got { 124 println("testLoadCombine failed, wanted", want, "got", got) 125 failed = true 126 } 127 } 128 129 var loadSymData = [...]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08} 130 131 func testLoadSymCombine() { 132 w2 := uint16(0x0201) 133 g2 := uint16(loadSymData[0]) | uint16(loadSymData[1])<<8 134 if g2 != w2 { 135 println("testLoadSymCombine failed, wanted", w2, "got", g2) 136 failed = true 137 } 138 w4 := uint32(0x04030201) 139 g4 := uint32(loadSymData[0]) | uint32(loadSymData[1])<<8 | 140 uint32(loadSymData[2])<<16 | uint32(loadSymData[3])<<24 141 if g4 != w4 { 142 println("testLoadSymCombine failed, wanted", w4, "got", g4) 143 failed = true 144 } 145 w8 := uint64(0x0807060504030201) 146 g8 := uint64(loadSymData[0]) | uint64(loadSymData[1])<<8 | 147 uint64(loadSymData[2])<<16 | uint64(loadSymData[3])<<24 | 148 uint64(loadSymData[4])<<32 | uint64(loadSymData[5])<<40 | 149 uint64(loadSymData[6])<<48 | uint64(loadSymData[7])<<56 150 if g8 != w8 { 151 println("testLoadSymCombine failed, wanted", w8, "got", g8) 152 failed = true 153 } 154 } 155 156 //go:noinline 157 func invalidAdd_ssa(x uint32) uint32 { 158 return x + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y 159 } 160 161 //go:noinline 162 func invalidSub_ssa(x uint32) uint32 { 163 return x - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y 164 } 165 166 //go:noinline 167 func invalidMul_ssa(x uint32) uint32 { 168 return x * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y 169 } 170 171 // testLargeConst tests a situation where larger than 32 bit consts were passed to ADDL 172 // causing an invalid instruction error. 173 func testLargeConst() { 174 if want, got := uint32(268435440), invalidAdd_ssa(1); want != got { 175 println("testLargeConst add failed, wanted", want, "got", got) 176 failed = true 177 } 178 if want, got := uint32(4026531858), invalidSub_ssa(1); want != got { 179 println("testLargeConst sub failed, wanted", want, "got", got) 180 failed = true 181 } 182 if want, got := uint32(268435455), invalidMul_ssa(1); want != got { 183 println("testLargeConst mul failed, wanted", want, "got", got) 184 failed = true 185 } 186 } 187 188 // testArithRshConst ensures that "const >> const" right shifts correctly perform 189 // sign extension on the lhs constant 190 func testArithRshConst() { 191 wantu := uint64(0x4000000000000000) 192 if got := arithRshuConst_ssa(); got != wantu { 193 println("arithRshuConst failed, wanted", wantu, "got", got) 194 failed = true 195 } 196 197 wants := int64(-0x4000000000000000) 198 if got := arithRshConst_ssa(); got != wants { 199 println("arithRshuConst failed, wanted", wants, "got", got) 200 failed = true 201 } 202 } 203 204 //go:noinline 205 func arithRshuConst_ssa() uint64 { 206 y := uint64(0x8000000000000001) 207 z := uint64(1) 208 return uint64(y >> z) 209 } 210 211 //go:noinline 212 func arithRshConst_ssa() int64 { 213 y := int64(-0x8000000000000000) 214 z := uint64(1) 215 return int64(y >> z) 216 } 217 218 //go:noinline 219 func arithConstShift_ssa(x int64) int64 { 220 return x >> 100 221 } 222 223 // testArithConstShift tests that right shift by large constants preserve 224 // the sign of the input. 225 func testArithConstShift() { 226 want := int64(-1) 227 if got := arithConstShift_ssa(-1); want != got { 228 println("arithConstShift_ssa(-1) failed, wanted", want, "got", got) 229 failed = true 230 } 231 want = 0 232 if got := arithConstShift_ssa(1); want != got { 233 println("arithConstShift_ssa(1) failed, wanted", want, "got", got) 234 failed = true 235 } 236 } 237 238 // overflowConstShift_ssa verifes that constant folding for shift 239 // doesn't wrap (i.e. x << MAX_INT << 1 doesn't get folded to x << 0). 240 //go:noinline 241 func overflowConstShift64_ssa(x int64) int64 { 242 return x << uint64(0xffffffffffffffff) << uint64(1) 243 } 244 245 //go:noinline 246 func overflowConstShift32_ssa(x int64) int32 { 247 return int32(x) << uint32(0xffffffff) << uint32(1) 248 } 249 250 //go:noinline 251 func overflowConstShift16_ssa(x int64) int16 { 252 return int16(x) << uint16(0xffff) << uint16(1) 253 } 254 255 //go:noinline 256 func overflowConstShift8_ssa(x int64) int8 { 257 return int8(x) << uint8(0xff) << uint8(1) 258 } 259 260 func testOverflowConstShift() { 261 want := int64(0) 262 for x := int64(-127); x < int64(127); x++ { 263 got := overflowConstShift64_ssa(x) 264 if want != got { 265 fmt.Printf("overflowShift64 failed, wanted %d got %d\n", want, got) 266 } 267 got = int64(overflowConstShift32_ssa(x)) 268 if want != got { 269 fmt.Printf("overflowShift32 failed, wanted %d got %d\n", want, got) 270 } 271 got = int64(overflowConstShift16_ssa(x)) 272 if want != got { 273 fmt.Printf("overflowShift16 failed, wanted %d got %d\n", want, got) 274 } 275 got = int64(overflowConstShift8_ssa(x)) 276 if want != got { 277 fmt.Printf("overflowShift8 failed, wanted %d got %d\n", want, got) 278 } 279 } 280 } 281 282 // test64BitConstMult tests that rewrite rules don't fold 64 bit constants 283 // into multiply instructions. 284 func test64BitConstMult() { 285 want := int64(103079215109) 286 if got := test64BitConstMult_ssa(1, 2); want != got { 287 println("test64BitConstMult failed, wanted", want, "got", got) 288 failed = true 289 } 290 } 291 292 //go:noinline 293 func test64BitConstMult_ssa(a, b int64) int64 { 294 return 34359738369*a + b*34359738370 295 } 296 297 // test64BitConstAdd tests that rewrite rules don't fold 64 bit constants 298 // into add instructions. 299 func test64BitConstAdd() { 300 want := int64(3567671782835376650) 301 if got := test64BitConstAdd_ssa(1, 2); want != got { 302 println("test64BitConstAdd failed, wanted", want, "got", got) 303 failed = true 304 } 305 } 306 307 //go:noinline 308 func test64BitConstAdd_ssa(a, b int64) int64 { 309 return a + 575815584948629622 + b + 2991856197886747025 310 } 311 312 // testRegallocCVSpill tests that regalloc spills a value whose last use is the 313 // current value. 314 func testRegallocCVSpill() { 315 want := int8(-9) 316 if got := testRegallocCVSpill_ssa(1, 2, 3, 4); want != got { 317 println("testRegallocCVSpill failed, wanted", want, "got", got) 318 failed = true 319 } 320 } 321 322 //go:noinline 323 func testRegallocCVSpill_ssa(a, b, c, d int8) int8 { 324 return a + -32 + b + 63*c*-87*d 325 } 326 327 func testBitwiseLogic() { 328 a, b := uint32(57623283), uint32(1314713839) 329 if want, got := uint32(38551779), testBitwiseAnd_ssa(a, b); want != got { 330 println("testBitwiseAnd failed, wanted", want, "got", got) 331 failed = true 332 } 333 if want, got := uint32(1333785343), testBitwiseOr_ssa(a, b); want != got { 334 println("testBitwiseOr failed, wanted", want, "got", got) 335 failed = true 336 } 337 if want, got := uint32(1295233564), testBitwiseXor_ssa(a, b); want != got { 338 println("testBitwiseXor failed, wanted", want, "got", got) 339 failed = true 340 } 341 if want, got := int32(832), testBitwiseLsh_ssa(13, 4, 2); want != got { 342 println("testBitwiseLsh failed, wanted", want, "got", got) 343 failed = true 344 } 345 if want, got := int32(0), testBitwiseLsh_ssa(13, 25, 15); want != got { 346 println("testBitwiseLsh failed, wanted", want, "got", got) 347 failed = true 348 } 349 if want, got := int32(0), testBitwiseLsh_ssa(-13, 25, 15); want != got { 350 println("testBitwiseLsh failed, wanted", want, "got", got) 351 failed = true 352 } 353 if want, got := int32(-13), testBitwiseRsh_ssa(-832, 4, 2); want != got { 354 println("testBitwiseRsh failed, wanted", want, "got", got) 355 failed = true 356 } 357 if want, got := int32(0), testBitwiseRsh_ssa(13, 25, 15); want != got { 358 println("testBitwiseRsh failed, wanted", want, "got", got) 359 failed = true 360 } 361 if want, got := int32(-1), testBitwiseRsh_ssa(-13, 25, 15); want != got { 362 println("testBitwiseRsh failed, wanted", want, "got", got) 363 failed = true 364 } 365 if want, got := uint32(0x3ffffff), testBitwiseRshU_ssa(0xffffffff, 4, 2); want != got { 366 println("testBitwiseRshU failed, wanted", want, "got", got) 367 failed = true 368 } 369 if want, got := uint32(0), testBitwiseRshU_ssa(13, 25, 15); want != got { 370 println("testBitwiseRshU failed, wanted", want, "got", got) 371 failed = true 372 } 373 if want, got := uint32(0), testBitwiseRshU_ssa(0x8aaaaaaa, 25, 15); want != got { 374 println("testBitwiseRshU failed, wanted", want, "got", got) 375 failed = true 376 } 377 } 378 379 //go:noinline 380 func testBitwiseAnd_ssa(a, b uint32) uint32 { 381 return a & b 382 } 383 384 //go:noinline 385 func testBitwiseOr_ssa(a, b uint32) uint32 { 386 return a | b 387 } 388 389 //go:noinline 390 func testBitwiseXor_ssa(a, b uint32) uint32 { 391 return a ^ b 392 } 393 394 //go:noinline 395 func testBitwiseLsh_ssa(a int32, b, c uint32) int32 { 396 return a << b << c 397 } 398 399 //go:noinline 400 func testBitwiseRsh_ssa(a int32, b, c uint32) int32 { 401 return a >> b >> c 402 } 403 404 //go:noinline 405 func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 { 406 return a >> b >> c 407 } 408 409 //go:noinline 410 func testShiftCX_ssa() int { 411 v1 := uint8(3) 412 v4 := (v1 * v1) ^ v1 | v1 - v1 - v1&v1 ^ uint8(3+2) + v1*1>>0 - v1 | 1 | v1<<(2*3|0-0*0^1) 413 v5 := v4>>(3-0-uint(3)) | v1 | v1 + v1 ^ v4<<(0+1|3&1)<<(uint64(1)<<0*2*0<<0) ^ v1 414 v6 := v5 ^ (v1+v1)*v1 | v1 | v1*v1>>(v1&v1)>>(uint(1)<<0*uint(3)>>1)*v1<<2*v1<<v1 - v1>>2 | (v4 - v1) ^ v1 + v1 ^ v1>>1 | v1 + v1 - v1 ^ v1 415 v7 := v6 & v5 << 0 416 v1++ 417 v11 := 2&1 ^ 0 + 3 | int(0^0)<<1>>(1*0*3) ^ 0*0 ^ 3&0*3&3 ^ 3*3 ^ 1 ^ int(2)<<(2*3) + 2 | 2 | 2 ^ 2 + 1 | 3 | 0 ^ int(1)>>1 ^ 2 // int 418 v7-- 419 return int(uint64(2*1)<<(3-2)<<uint(3>>v7)-2)&v11 | v11 - int(2)<<0>>(2-1)*(v11*0&v11<<1<<(uint8(2)+v4)) 420 } 421 422 func testShiftCX() { 423 want := 141 424 if got := testShiftCX_ssa(); want != got { 425 println("testShiftCX failed, wanted", want, "got", got) 426 failed = true 427 } 428 } 429 430 // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. 431 func testSubqToNegq() { 432 want := int64(-318294940372190156) 433 if got := testSubqToNegq_ssa(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2); want != got { 434 println("testSubqToNegq failed, wanted", want, "got", got) 435 failed = true 436 } 437 } 438 439 //go:noinline 440 func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 { 441 return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 442 } 443 444 func testOcom() { 445 want1, want2 := int32(0x55555555), int32(-0x55555556) 446 if got1, got2 := testOcom_ssa(0x55555555, 0x55555555); want1 != got1 || want2 != got2 { 447 println("testSubqToNegq failed, wanted", want1, "and", want2, 448 "got", got1, "and", got2) 449 failed = true 450 } 451 } 452 453 //go:noinline 454 func testOcom_ssa(a, b int32) (int32, int32) { 455 return ^^^^a, ^^^^^b 456 } 457 458 func lrot1_ssa(w uint8, x uint16, y uint32, z uint64) (a uint8, b uint16, c uint32, d uint64) { 459 a = (w << 5) | (w >> 3) 460 b = (x << 13) | (x >> 3) 461 c = (y << 29) | (y >> 3) 462 d = (z << 61) | (z >> 3) 463 return 464 } 465 466 //go:noinline 467 func lrot2_ssa(w, n uint32) uint32 { 468 // Want to be sure that a "rotate by 32" which 469 // is really 0 | (w >> 0) == w 470 // is correctly compiled. 471 return (w << n) | (w >> (32 - n)) 472 } 473 474 //go:noinline 475 func lrot3_ssa(w uint32) uint32 { 476 // Want to be sure that a "rotate by 32" which 477 // is really 0 | (w >> 0) == w 478 // is correctly compiled. 479 return (w << 32) | (w >> (32 - 32)) 480 } 481 482 func testLrot() { 483 wantA, wantB, wantC, wantD := uint8(0xe1), uint16(0xe001), 484 uint32(0xe0000001), uint64(0xe000000000000001) 485 a, b, c, d := lrot1_ssa(0xf, 0xf, 0xf, 0xf) 486 if a != wantA || b != wantB || c != wantC || d != wantD { 487 println("lrot1_ssa(0xf, 0xf, 0xf, 0xf)=", 488 wantA, wantB, wantC, wantD, ", got", a, b, c, d) 489 failed = true 490 } 491 x := lrot2_ssa(0xb0000001, 32) 492 wantX := uint32(0xb0000001) 493 if x != wantX { 494 println("lrot2_ssa(0xb0000001, 32)=", 495 wantX, ", got", x) 496 failed = true 497 } 498 x = lrot3_ssa(0xb0000001) 499 if x != wantX { 500 println("lrot3_ssa(0xb0000001)=", 501 wantX, ", got", x) 502 failed = true 503 } 504 505 } 506 507 //go:noinline 508 func sub1_ssa() uint64 { 509 v1 := uint64(3) // uint64 510 return v1*v1 - (v1&v1)&v1 511 } 512 513 //go:noinline 514 func sub2_ssa() uint8 { 515 v1 := uint8(0) 516 v3 := v1 + v1 + v1 ^ v1 | 3 + v1 ^ v1 | v1 ^ v1 517 v1-- // dev.ssa doesn't see this one 518 return v1 ^ v1*v1 - v3 519 } 520 521 func testSubConst() { 522 x1 := sub1_ssa() 523 want1 := uint64(6) 524 if x1 != want1 { 525 println("sub1_ssa()=", want1, ", got", x1) 526 failed = true 527 } 528 x2 := sub2_ssa() 529 want2 := uint8(251) 530 if x2 != want2 { 531 println("sub2_ssa()=", want2, ", got", x2) 532 failed = true 533 } 534 } 535 536 //go:noinline 537 func orPhi_ssa(a bool, x int) int { 538 v := 0 539 if a { 540 v = -1 541 } else { 542 v = -1 543 } 544 return x | v 545 } 546 547 func testOrPhi() { 548 if want, got := -1, orPhi_ssa(true, 4); got != want { 549 println("orPhi_ssa(true, 4)=", got, " want ", want) 550 } 551 if want, got := -1, orPhi_ssa(false, 0); got != want { 552 println("orPhi_ssa(false, 0)=", got, " want ", want) 553 } 554 } 555 556 var failed = false 557 558 func main() { 559 560 test64BitConstMult() 561 test64BitConstAdd() 562 testRegallocCVSpill() 563 testSubqToNegq() 564 testBitwiseLogic() 565 testOcom() 566 testLrot() 567 testShiftCX() 568 testSubConst() 569 testOverflowConstShift() 570 testArithConstShift() 571 testArithRshConst() 572 testLargeConst() 573 testLoadCombine() 574 testLoadSymCombine() 575 testShiftRemoval() 576 577 if failed { 578 panic("failed") 579 } 580 }