1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "Reactor.hpp" 16 17 #include "Optimizer.hpp" 18 19 #include "src/IceTypes.h" 20 #include "src/IceCfg.h" 21 #include "src/IceELFStreamer.h" 22 #include "src/IceGlobalContext.h" 23 #include "src/IceCfgNode.h" 24 #include "src/IceELFObjectWriter.h" 25 #include "src/IceGlobalInits.h" 26 27 #include "llvm/Support/FileSystem.h" 28 #include "llvm/Support/raw_os_ostream.h" 29 30 #if defined(_WIN32) 31 #ifndef WIN32_LEAN_AND_MEAN 32 #define WIN32_LEAN_AND_MEAN 33 #endif // !WIN32_LEAN_AND_MEAN 34 #ifndef NOMINMAX 35 #define NOMINMAX 36 #endif // !NOMINMAX 37 #include <Windows.h> 38 #else 39 #include <sys/mman.h> 40 #if !defined(MAP_ANONYMOUS) 41 #define MAP_ANONYMOUS MAP_ANON 42 #endif 43 #endif 44 45 //#include <mutex> 46 #include <limits> 47 #include <iostream> 48 #include <cassert> 49 50 namespace 51 { 52 Ice::GlobalContext *context = nullptr; 53 Ice::Cfg *function = nullptr; 54 Ice::CfgNode *basicBlock = nullptr; 55 Ice::CfgLocalAllocatorScope *allocator = nullptr; 56 sw::Routine *routine = nullptr; 57 58 std::mutex codegenMutex; 59 60 Ice::ELFFileStreamer *elfFile = nullptr; 61 Ice::Fdstream *out = nullptr; 62 } 63 64 namespace 65 { 66 #if !defined(__i386__) && defined(_M_IX86) 67 #define __i386__ 1 68 #endif 69 70 #if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64)) 71 #define __x86_64__ 1 72 #endif 73 74 class CPUID 75 { 76 public: 77 const static bool ARM; 78 const static bool SSE4_1; 79 80 private: 81 static void cpuid(int registers[4], int info) 82 { 83 #if defined(__i386__) || defined(__x86_64__) 84 #if defined(_WIN32) 85 __cpuid(registers, info); 86 #else 87 __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info)); 88 #endif 89 #else 90 registers[0] = 0; 91 registers[1] = 0; 92 registers[2] = 0; 93 registers[3] = 0; 94 #endif 95 } 96 97 static bool detectARM() 98 { 99 #if defined(__arm__) 100 return true; 101 #elif defined(__i386__) || defined(__x86_64__) 102 return false; 103 #else 104 #error "Unknown architecture" 105 #endif 106 } 107 108 static bool detectSSE4_1() 109 { 110 #if defined(__i386__) || defined(__x86_64__) 111 int registers[4]; 112 cpuid(registers, 1); 113 return (registers[2] & 0x00080000) != 0; 114 #else 115 return false; 116 #endif 117 } 118 }; 119 120 const bool CPUID::ARM = CPUID::detectARM(); 121 const bool CPUID::SSE4_1 = CPUID::detectSSE4_1(); 122 const bool emulateIntrinsics = false; 123 const bool emulateMismatchedBitCast = CPUID::ARM; 124 } 125 126 namespace sw 127 { 128 enum EmulatedType 129 { 130 EmulatedShift = 16, 131 EmulatedV2 = 2 << EmulatedShift, 132 EmulatedV4 = 4 << EmulatedShift, 133 EmulatedV8 = 8 << EmulatedShift, 134 EmulatedBits = EmulatedV2 | EmulatedV4 | EmulatedV8, 135 136 Type_v2i32 = Ice::IceType_v4i32 | EmulatedV2, 137 Type_v4i16 = Ice::IceType_v8i16 | EmulatedV4, 138 Type_v2i16 = Ice::IceType_v8i16 | EmulatedV2, 139 Type_v8i8 = Ice::IceType_v16i8 | EmulatedV8, 140 Type_v4i8 = Ice::IceType_v16i8 | EmulatedV4, 141 Type_v2f32 = Ice::IceType_v4f32 | EmulatedV2, 142 }; 143 144 class Value : public Ice::Operand {}; 145 class SwitchCases : public Ice::InstSwitch {}; 146 class BasicBlock : public Ice::CfgNode {}; 147 148 Ice::Type T(Type *t) 149 { 150 static_assert(static_cast<unsigned int>(Ice::IceType_NUM) < static_cast<unsigned int>(EmulatedBits), "Ice::Type overlaps with our emulated types!"); 151 return (Ice::Type)(reinterpret_cast<std::intptr_t>(t) & ~EmulatedBits); 152 } 153 154 Type *T(Ice::Type t) 155 { 156 return reinterpret_cast<Type*>(t); 157 } 158 159 Type *T(EmulatedType t) 160 { 161 return reinterpret_cast<Type*>(t); 162 } 163 164 Value *V(Ice::Operand *v) 165 { 166 return reinterpret_cast<Value*>(v); 167 } 168 169 BasicBlock *B(Ice::CfgNode *b) 170 { 171 return reinterpret_cast<BasicBlock*>(b); 172 } 173 174 static size_t typeSize(Type *type) 175 { 176 if(reinterpret_cast<std::intptr_t>(type) & EmulatedBits) 177 { 178 switch(reinterpret_cast<std::intptr_t>(type)) 179 { 180 case Type_v2i32: return 8; 181 case Type_v4i16: return 8; 182 case Type_v2i16: return 4; 183 case Type_v8i8: return 8; 184 case Type_v4i8: return 4; 185 case Type_v2f32: return 8; 186 default: assert(false); 187 } 188 } 189 190 return Ice::typeWidthInBytes(T(type)); 191 } 192 193 Optimization optimization[10] = {InstructionCombining, Disabled}; 194 195 using ElfHeader = std::conditional<sizeof(void*) == 8, Elf64_Ehdr, Elf32_Ehdr>::type; 196 using SectionHeader = std::conditional<sizeof(void*) == 8, Elf64_Shdr, Elf32_Shdr>::type; 197 198 inline const SectionHeader *sectionHeader(const ElfHeader *elfHeader) 199 { 200 return reinterpret_cast<const SectionHeader*>((intptr_t)elfHeader + elfHeader->e_shoff); 201 } 202 203 inline const SectionHeader *elfSection(const ElfHeader *elfHeader, int index) 204 { 205 return §ionHeader(elfHeader)[index]; 206 } 207 208 static void *relocateSymbol(const ElfHeader *elfHeader, const Elf32_Rel &relocation, const SectionHeader &relocationTable) 209 { 210 const SectionHeader *target = elfSection(elfHeader, relocationTable.sh_info); 211 212 intptr_t address = (intptr_t)elfHeader + target->sh_offset; 213 int32_t *patchSite = (int*)(address + relocation.r_offset); 214 uint32_t index = relocation.getSymbol(); 215 int table = relocationTable.sh_link; 216 void *symbolValue = nullptr; 217 218 if(index != SHN_UNDEF) 219 { 220 if(table == SHN_UNDEF) return nullptr; 221 const SectionHeader *symbolTable = elfSection(elfHeader, table); 222 223 uint32_t symtab_entries = symbolTable->sh_size / symbolTable->sh_entsize; 224 if(index >= symtab_entries) 225 { 226 assert(index < symtab_entries && "Symbol Index out of range"); 227 return nullptr; 228 } 229 230 intptr_t symbolAddress = (intptr_t)elfHeader + symbolTable->sh_offset; 231 Elf32_Sym &symbol = ((Elf32_Sym*)symbolAddress)[index]; 232 uint16_t section = symbol.st_shndx; 233 234 if(section != SHN_UNDEF && section < SHN_LORESERVE) 235 { 236 const SectionHeader *target = elfSection(elfHeader, symbol.st_shndx); 237 symbolValue = reinterpret_cast<void*>((intptr_t)elfHeader + symbol.st_value + target->sh_offset); 238 } 239 else 240 { 241 return nullptr; 242 } 243 } 244 245 if(CPUID::ARM) 246 { 247 switch(relocation.getType()) 248 { 249 case R_ARM_NONE: 250 // No relocation 251 break; 252 case R_ARM_MOVW_ABS_NC: 253 { 254 uint32_t thumb = 0; // Calls to Thumb code not supported. 255 uint32_t lo = (uint32_t)(intptr_t)symbolValue | thumb; 256 *patchSite = (*patchSite & 0xFFF0F000) | ((lo & 0xF000) << 4) | (lo & 0x0FFF); 257 } 258 break; 259 case R_ARM_MOVT_ABS: 260 { 261 uint32_t hi = (uint32_t)(intptr_t)(symbolValue) >> 16; 262 *patchSite = (*patchSite & 0xFFF0F000) | ((hi & 0xF000) << 4) | (hi & 0x0FFF); 263 } 264 break; 265 default: 266 assert(false && "Unsupported relocation type"); 267 return nullptr; 268 } 269 } 270 else 271 { 272 switch(relocation.getType()) 273 { 274 case R_386_NONE: 275 // No relocation 276 break; 277 case R_386_32: 278 *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite); 279 break; 280 // case R_386_PC32: 281 // *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite - (intptr_t)patchSite); 282 // break; 283 default: 284 assert(false && "Unsupported relocation type"); 285 return nullptr; 286 } 287 } 288 289 return symbolValue; 290 } 291 292 static void *relocateSymbol(const ElfHeader *elfHeader, const Elf64_Rela &relocation, const SectionHeader &relocationTable) 293 { 294 const SectionHeader *target = elfSection(elfHeader, relocationTable.sh_info); 295 296 intptr_t address = (intptr_t)elfHeader + target->sh_offset; 297 int32_t *patchSite = (int*)(address + relocation.r_offset); 298 uint32_t index = relocation.getSymbol(); 299 int table = relocationTable.sh_link; 300 void *symbolValue = nullptr; 301 302 if(index != SHN_UNDEF) 303 { 304 if(table == SHN_UNDEF) return nullptr; 305 const SectionHeader *symbolTable = elfSection(elfHeader, table); 306 307 uint32_t symtab_entries = symbolTable->sh_size / symbolTable->sh_entsize; 308 if(index >= symtab_entries) 309 { 310 assert(index < symtab_entries && "Symbol Index out of range"); 311 return nullptr; 312 } 313 314 intptr_t symbolAddress = (intptr_t)elfHeader + symbolTable->sh_offset; 315 Elf64_Sym &symbol = ((Elf64_Sym*)symbolAddress)[index]; 316 uint16_t section = symbol.st_shndx; 317 318 if(section != SHN_UNDEF && section < SHN_LORESERVE) 319 { 320 const SectionHeader *target = elfSection(elfHeader, symbol.st_shndx); 321 symbolValue = reinterpret_cast<void*>((intptr_t)elfHeader + symbol.st_value + target->sh_offset); 322 } 323 else 324 { 325 return nullptr; 326 } 327 } 328 329 switch(relocation.getType()) 330 { 331 case R_X86_64_NONE: 332 // No relocation 333 break; 334 case R_X86_64_64: 335 *(int64_t*)patchSite = (int64_t)((intptr_t)symbolValue + *(int64_t*)patchSite) + relocation.r_addend; 336 break; 337 case R_X86_64_PC32: 338 *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite - (intptr_t)patchSite) + relocation.r_addend; 339 break; 340 case R_X86_64_32S: 341 *patchSite = (int32_t)((intptr_t)symbolValue + *patchSite) + relocation.r_addend; 342 break; 343 default: 344 assert(false && "Unsupported relocation type"); 345 return nullptr; 346 } 347 348 return symbolValue; 349 } 350 351 void *loadImage(uint8_t *const elfImage, size_t &codeSize) 352 { 353 ElfHeader *elfHeader = (ElfHeader*)elfImage; 354 355 if(!elfHeader->checkMagic()) 356 { 357 return nullptr; 358 } 359 360 // Expect ELF bitness to match platform 361 assert(sizeof(void*) == 8 ? elfHeader->getFileClass() == ELFCLASS64 : elfHeader->getFileClass() == ELFCLASS32); 362 #if defined(__i386__) 363 assert(sizeof(void*) == 4 && elfHeader->e_machine == EM_386); 364 #elif defined(__x86_64__) 365 assert(sizeof(void*) == 8 && elfHeader->e_machine == EM_X86_64); 366 #elif defined(__arm__) 367 assert(sizeof(void*) == 4 && elfHeader->e_machine == EM_ARM); 368 #else 369 #error "Unsupported platform" 370 #endif 371 372 SectionHeader *sectionHeader = (SectionHeader*)(elfImage + elfHeader->e_shoff); 373 void *entry = nullptr; 374 375 for(int i = 0; i < elfHeader->e_shnum; i++) 376 { 377 if(sectionHeader[i].sh_type == SHT_PROGBITS) 378 { 379 if(sectionHeader[i].sh_flags & SHF_EXECINSTR) 380 { 381 entry = elfImage + sectionHeader[i].sh_offset; 382 codeSize = sectionHeader[i].sh_size; 383 } 384 } 385 else if(sectionHeader[i].sh_type == SHT_REL) 386 { 387 assert(sizeof(void*) == 4 && "UNIMPLEMENTED"); // Only expected/implemented for 32-bit code 388 389 for(Elf32_Word index = 0; index < sectionHeader[i].sh_size / sectionHeader[i].sh_entsize; index++) 390 { 391 const Elf32_Rel &relocation = ((const Elf32_Rel*)(elfImage + sectionHeader[i].sh_offset))[index]; 392 relocateSymbol(elfHeader, relocation, sectionHeader[i]); 393 } 394 } 395 else if(sectionHeader[i].sh_type == SHT_RELA) 396 { 397 assert(sizeof(void*) == 8 && "UNIMPLEMENTED"); // Only expected/implemented for 64-bit code 398 399 for(Elf32_Word index = 0; index < sectionHeader[i].sh_size / sectionHeader[i].sh_entsize; index++) 400 { 401 const Elf64_Rela &relocation = ((const Elf64_Rela*)(elfImage + sectionHeader[i].sh_offset))[index]; 402 relocateSymbol(elfHeader, relocation, sectionHeader[i]); 403 } 404 } 405 } 406 407 return entry; 408 } 409 410 template<typename T> 411 struct ExecutableAllocator 412 { 413 ExecutableAllocator() {}; 414 template<class U> ExecutableAllocator(const ExecutableAllocator<U> &other) {}; 415 416 using value_type = T; 417 using size_type = std::size_t; 418 419 T *allocate(size_type n) 420 { 421 #if defined(_WIN32) 422 return (T*)VirtualAlloc(NULL, sizeof(T) * n, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 423 #else 424 return (T*)mmap(nullptr, sizeof(T) * n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 425 #endif 426 } 427 428 void deallocate(T *p, size_type n) 429 { 430 #if defined(_WIN32) 431 VirtualFree(p, 0, MEM_RELEASE); 432 #else 433 munmap(p, sizeof(T) * n); 434 #endif 435 } 436 }; 437 438 class ELFMemoryStreamer : public Ice::ELFStreamer, public Routine 439 { 440 ELFMemoryStreamer(const ELFMemoryStreamer &) = delete; 441 ELFMemoryStreamer &operator=(const ELFMemoryStreamer &) = delete; 442 443 public: 444 ELFMemoryStreamer() : Routine(), entry(nullptr) 445 { 446 position = 0; 447 buffer.reserve(0x1000); 448 } 449 450 ~ELFMemoryStreamer() override 451 { 452 #if defined(_WIN32) 453 if(buffer.size() != 0) 454 { 455 DWORD exeProtection; 456 VirtualProtect(&buffer[0], buffer.size(), oldProtection, &exeProtection); 457 } 458 #endif 459 } 460 461 void write8(uint8_t Value) override 462 { 463 if(position == (uint64_t)buffer.size()) 464 { 465 buffer.push_back(Value); 466 position++; 467 } 468 else if(position < (uint64_t)buffer.size()) 469 { 470 buffer[position] = Value; 471 position++; 472 } 473 else assert(false && "UNIMPLEMENTED"); 474 } 475 476 void writeBytes(llvm::StringRef Bytes) override 477 { 478 std::size_t oldSize = buffer.size(); 479 buffer.resize(oldSize + Bytes.size()); 480 memcpy(&buffer[oldSize], Bytes.begin(), Bytes.size()); 481 position += Bytes.size(); 482 } 483 484 uint64_t tell() const override { return position; } 485 486 void seek(uint64_t Off) override { position = Off; } 487 488 const void *getEntry() override 489 { 490 if(!entry) 491 { 492 position = std::numeric_limits<std::size_t>::max(); // Can't stream more data after this 493 494 size_t codeSize = 0; 495 entry = loadImage(&buffer[0], codeSize); 496 497 #if defined(_WIN32) 498 VirtualProtect(&buffer[0], buffer.size(), PAGE_EXECUTE_READ, &oldProtection); 499 FlushInstructionCache(GetCurrentProcess(), NULL, 0); 500 #else 501 mprotect(&buffer[0], buffer.size(), PROT_READ | PROT_EXEC); 502 __builtin___clear_cache((char*)entry, (char*)entry + codeSize); 503 #endif 504 } 505 506 return entry; 507 } 508 509 private: 510 void *entry; 511 std::vector<uint8_t, ExecutableAllocator<uint8_t>> buffer; 512 std::size_t position; 513 514 #if defined(_WIN32) 515 DWORD oldProtection; 516 #endif 517 }; 518 519 Nucleus::Nucleus() 520 { 521 ::codegenMutex.lock(); // Reactor is currently not thread safe 522 523 Ice::ClFlags &Flags = Ice::ClFlags::Flags; 524 Ice::ClFlags::getParsedClFlags(Flags); 525 526 #if defined(__arm__) 527 Flags.setTargetArch(Ice::Target_ARM32); 528 Flags.setTargetInstructionSet(Ice::ARM32InstructionSet_HWDivArm); 529 #else // x86 530 Flags.setTargetArch(sizeof(void*) == 8 ? Ice::Target_X8664 : Ice::Target_X8632); 531 Flags.setTargetInstructionSet(CPUID::SSE4_1 ? Ice::X86InstructionSet_SSE4_1 : Ice::X86InstructionSet_SSE2); 532 #endif 533 Flags.setOutFileType(Ice::FT_Elf); 534 Flags.setOptLevel(Ice::Opt_2); 535 Flags.setApplicationBinaryInterface(Ice::ABI_Platform); 536 Flags.setVerbose(false ? Ice::IceV_Most : Ice::IceV_None); 537 Flags.setDisableHybridAssembly(true); 538 539 static llvm::raw_os_ostream cout(std::cout); 540 static llvm::raw_os_ostream cerr(std::cerr); 541 542 if(false) // Write out to a file 543 { 544 std::error_code errorCode; 545 ::out = new Ice::Fdstream("out.o", errorCode, llvm::sys::fs::F_None); 546 ::elfFile = new Ice::ELFFileStreamer(*out); 547 ::context = new Ice::GlobalContext(&cout, &cout, &cerr, elfFile); 548 } 549 else 550 { 551 ELFMemoryStreamer *elfMemory = new ELFMemoryStreamer(); 552 ::context = new Ice::GlobalContext(&cout, &cout, &cerr, elfMemory); 553 ::routine = elfMemory; 554 } 555 } 556 557 Nucleus::~Nucleus() 558 { 559 delete ::routine; 560 561 delete ::allocator; 562 delete ::function; 563 delete ::context; 564 565 delete ::elfFile; 566 delete ::out; 567 568 ::codegenMutex.unlock(); 569 } 570 571 Routine *Nucleus::acquireRoutine(const wchar_t *name, bool runOptimizations) 572 { 573 if(basicBlock->getInsts().empty() || basicBlock->getInsts().back().getKind() != Ice::Inst::Ret) 574 { 575 createRetVoid(); 576 } 577 578 std::wstring wideName(name); 579 std::string asciiName(wideName.begin(), wideName.end()); 580 ::function->setFunctionName(Ice::GlobalString::createWithString(::context, asciiName)); 581 582 optimize(); 583 584 ::function->translate(); 585 assert(!::function->hasError()); 586 587 auto globals = ::function->getGlobalInits(); 588 589 if(globals && !globals->empty()) 590 { 591 ::context->getGlobals()->merge(globals.get()); 592 } 593 594 ::context->emitFileHeader(); 595 ::function->emitIAS(); 596 auto assembler = ::function->releaseAssembler(); 597 auto objectWriter = ::context->getObjectWriter(); 598 assembler->alignFunction(); 599 objectWriter->writeFunctionCode(::function->getFunctionName(), false, assembler.get()); 600 ::context->lowerGlobals("last"); 601 ::context->lowerConstants(); 602 ::context->lowerJumpTables(); 603 objectWriter->setUndefinedSyms(::context->getConstantExternSyms()); 604 objectWriter->writeNonUserSections(); 605 606 Routine *handoffRoutine = ::routine; 607 ::routine = nullptr; 608 609 return handoffRoutine; 610 } 611 612 void Nucleus::optimize() 613 { 614 sw::optimize(::function); 615 } 616 617 Value *Nucleus::allocateStackVariable(Type *t, int arraySize) 618 { 619 Ice::Type type = T(t); 620 int typeSize = Ice::typeWidthInBytes(type); 621 int totalSize = typeSize * (arraySize ? arraySize : 1); 622 623 auto bytes = Ice::ConstantInteger32::create(::context, type, totalSize); 624 auto address = ::function->makeVariable(T(getPointerType(t))); 625 auto alloca = Ice::InstAlloca::create(::function, address, bytes, typeSize); 626 ::function->getEntryNode()->getInsts().push_front(alloca); 627 628 return V(address); 629 } 630 631 BasicBlock *Nucleus::createBasicBlock() 632 { 633 return B(::function->makeNode()); 634 } 635 636 BasicBlock *Nucleus::getInsertBlock() 637 { 638 return B(::basicBlock); 639 } 640 641 void Nucleus::setInsertBlock(BasicBlock *basicBlock) 642 { 643 // assert(::basicBlock->getInsts().back().getTerminatorEdges().size() >= 0 && "Previous basic block must have a terminator"); 644 ::basicBlock = basicBlock; 645 } 646 647 void Nucleus::createFunction(Type *ReturnType, std::vector<Type*> &Params) 648 { 649 uint32_t sequenceNumber = 0; 650 ::function = Ice::Cfg::create(::context, sequenceNumber).release(); 651 ::allocator = new Ice::CfgLocalAllocatorScope(::function); 652 653 for(Type *type : Params) 654 { 655 Ice::Variable *arg = ::function->makeVariable(T(type)); 656 ::function->addArg(arg); 657 } 658 659 Ice::CfgNode *node = ::function->makeNode(); 660 ::function->setEntryNode(node); 661 ::basicBlock = node; 662 } 663 664 Value *Nucleus::getArgument(unsigned int index) 665 { 666 return V(::function->getArgs()[index]); 667 } 668 669 void Nucleus::createRetVoid() 670 { 671 Ice::InstRet *ret = Ice::InstRet::create(::function); 672 ::basicBlock->appendInst(ret); 673 } 674 675 void Nucleus::createRet(Value *v) 676 { 677 Ice::InstRet *ret = Ice::InstRet::create(::function, v); 678 ::basicBlock->appendInst(ret); 679 } 680 681 void Nucleus::createBr(BasicBlock *dest) 682 { 683 auto br = Ice::InstBr::create(::function, dest); 684 ::basicBlock->appendInst(br); 685 } 686 687 void Nucleus::createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse) 688 { 689 auto br = Ice::InstBr::create(::function, cond, ifTrue, ifFalse); 690 ::basicBlock->appendInst(br); 691 } 692 693 static bool isCommutative(Ice::InstArithmetic::OpKind op) 694 { 695 switch(op) 696 { 697 case Ice::InstArithmetic::Add: 698 case Ice::InstArithmetic::Fadd: 699 case Ice::InstArithmetic::Mul: 700 case Ice::InstArithmetic::Fmul: 701 case Ice::InstArithmetic::And: 702 case Ice::InstArithmetic::Or: 703 case Ice::InstArithmetic::Xor: 704 return true; 705 default: 706 return false; 707 } 708 } 709 710 static Value *createArithmetic(Ice::InstArithmetic::OpKind op, Value *lhs, Value *rhs) 711 { 712 assert(lhs->getType() == rhs->getType() || llvm::isa<Ice::Constant>(rhs)); 713 714 bool swapOperands = llvm::isa<Ice::Constant>(lhs) && isCommutative(op); 715 716 Ice::Variable *result = ::function->makeVariable(lhs->getType()); 717 Ice::InstArithmetic *arithmetic = Ice::InstArithmetic::create(::function, op, result, swapOperands ? rhs : lhs, swapOperands ? lhs : rhs); 718 ::basicBlock->appendInst(arithmetic); 719 720 return V(result); 721 } 722 723 Value *Nucleus::createAdd(Value *lhs, Value *rhs) 724 { 725 return createArithmetic(Ice::InstArithmetic::Add, lhs, rhs); 726 } 727 728 Value *Nucleus::createSub(Value *lhs, Value *rhs) 729 { 730 return createArithmetic(Ice::InstArithmetic::Sub, lhs, rhs); 731 } 732 733 Value *Nucleus::createMul(Value *lhs, Value *rhs) 734 { 735 return createArithmetic(Ice::InstArithmetic::Mul, lhs, rhs); 736 } 737 738 Value *Nucleus::createUDiv(Value *lhs, Value *rhs) 739 { 740 return createArithmetic(Ice::InstArithmetic::Udiv, lhs, rhs); 741 } 742 743 Value *Nucleus::createSDiv(Value *lhs, Value *rhs) 744 { 745 return createArithmetic(Ice::InstArithmetic::Sdiv, lhs, rhs); 746 } 747 748 Value *Nucleus::createFAdd(Value *lhs, Value *rhs) 749 { 750 return createArithmetic(Ice::InstArithmetic::Fadd, lhs, rhs); 751 } 752 753 Value *Nucleus::createFSub(Value *lhs, Value *rhs) 754 { 755 return createArithmetic(Ice::InstArithmetic::Fsub, lhs, rhs); 756 } 757 758 Value *Nucleus::createFMul(Value *lhs, Value *rhs) 759 { 760 return createArithmetic(Ice::InstArithmetic::Fmul, lhs, rhs); 761 } 762 763 Value *Nucleus::createFDiv(Value *lhs, Value *rhs) 764 { 765 return createArithmetic(Ice::InstArithmetic::Fdiv, lhs, rhs); 766 } 767 768 Value *Nucleus::createURem(Value *lhs, Value *rhs) 769 { 770 return createArithmetic(Ice::InstArithmetic::Urem, lhs, rhs); 771 } 772 773 Value *Nucleus::createSRem(Value *lhs, Value *rhs) 774 { 775 return createArithmetic(Ice::InstArithmetic::Srem, lhs, rhs); 776 } 777 778 Value *Nucleus::createFRem(Value *lhs, Value *rhs) 779 { 780 return createArithmetic(Ice::InstArithmetic::Frem, lhs, rhs); 781 } 782 783 Value *Nucleus::createShl(Value *lhs, Value *rhs) 784 { 785 return createArithmetic(Ice::InstArithmetic::Shl, lhs, rhs); 786 } 787 788 Value *Nucleus::createLShr(Value *lhs, Value *rhs) 789 { 790 return createArithmetic(Ice::InstArithmetic::Lshr, lhs, rhs); 791 } 792 793 Value *Nucleus::createAShr(Value *lhs, Value *rhs) 794 { 795 return createArithmetic(Ice::InstArithmetic::Ashr, lhs, rhs); 796 } 797 798 Value *Nucleus::createAnd(Value *lhs, Value *rhs) 799 { 800 return createArithmetic(Ice::InstArithmetic::And, lhs, rhs); 801 } 802 803 Value *Nucleus::createOr(Value *lhs, Value *rhs) 804 { 805 return createArithmetic(Ice::InstArithmetic::Or, lhs, rhs); 806 } 807 808 Value *Nucleus::createXor(Value *lhs, Value *rhs) 809 { 810 return createArithmetic(Ice::InstArithmetic::Xor, lhs, rhs); 811 } 812 813 Value *Nucleus::createNeg(Value *v) 814 { 815 return createSub(createNullValue(T(v->getType())), v); 816 } 817 818 Value *Nucleus::createFNeg(Value *v) 819 { 820 double c[4] = {-0.0, -0.0, -0.0, -0.0}; 821 Value *negativeZero = Ice::isVectorType(v->getType()) ? 822 createConstantVector(c, T(v->getType())) : 823 V(::context->getConstantFloat(-0.0f)); 824 825 return createFSub(negativeZero, v); 826 } 827 828 Value *Nucleus::createNot(Value *v) 829 { 830 if(Ice::isScalarIntegerType(v->getType())) 831 { 832 return createXor(v, V(::context->getConstantInt(v->getType(), -1))); 833 } 834 else // Vector 835 { 836 int64_t c[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 837 return createXor(v, createConstantVector(c, T(v->getType()))); 838 } 839 } 840 841 Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int align) 842 { 843 int valueType = (int)reinterpret_cast<intptr_t>(type); 844 Ice::Variable *result = ::function->makeVariable(T(type)); 845 846 if((valueType & EmulatedBits) && (align != 0)) // Narrow vector not stored on stack. 847 { 848 if(emulateIntrinsics) 849 { 850 if(typeSize(type) == 4) 851 { 852 auto pointer = RValue<Pointer<Byte>>(ptr); 853 Int x = *Pointer<Int>(pointer); 854 855 Int4 vector; 856 vector = Insert(vector, x, 0); 857 858 auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, result, vector.loadValue()); 859 ::basicBlock->appendInst(bitcast); 860 } 861 else if(typeSize(type) == 8) 862 { 863 auto pointer = RValue<Pointer<Byte>>(ptr); 864 Int x = *Pointer<Int>(pointer); 865 Int y = *Pointer<Int>(pointer + 4); 866 867 Int4 vector; 868 vector = Insert(vector, x, 0); 869 vector = Insert(vector, y, 1); 870 871 auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, result, vector.loadValue()); 872 ::basicBlock->appendInst(bitcast); 873 } 874 else assert(false); 875 } 876 else 877 { 878 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::LoadSubVector, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 879 auto target = ::context->getConstantUndef(Ice::IceType_i32); 880 auto load = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 881 load->addArg(ptr); 882 load->addArg(::context->getConstantInt32(typeSize(type))); 883 ::basicBlock->appendInst(load); 884 } 885 } 886 else 887 { 888 auto load = Ice::InstLoad::create(::function, result, ptr, align); 889 ::basicBlock->appendInst(load); 890 } 891 892 return V(result); 893 } 894 895 Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int align) 896 { 897 int valueType = (int)reinterpret_cast<intptr_t>(type); 898 899 if((valueType & EmulatedBits) && (align != 0)) // Narrow vector not stored on stack. 900 { 901 if(emulateIntrinsics) 902 { 903 if(typeSize(type) == 4) 904 { 905 Ice::Variable *vector = ::function->makeVariable(Ice::IceType_v4i32); 906 auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, vector, value); 907 ::basicBlock->appendInst(bitcast); 908 909 RValue<Int4> v(V(vector)); 910 911 auto pointer = RValue<Pointer<Byte>>(ptr); 912 Int x = Extract(v, 0); 913 *Pointer<Int>(pointer) = x; 914 } 915 else if(typeSize(type) == 8) 916 { 917 Ice::Variable *vector = ::function->makeVariable(Ice::IceType_v4i32); 918 auto bitcast = Ice::InstCast::create(::function, Ice::InstCast::Bitcast, vector, value); 919 ::basicBlock->appendInst(bitcast); 920 921 RValue<Int4> v(V(vector)); 922 923 auto pointer = RValue<Pointer<Byte>>(ptr); 924 Int x = Extract(v, 0); 925 *Pointer<Int>(pointer) = x; 926 Int y = Extract(v, 1); 927 *Pointer<Int>(pointer + 4) = y; 928 } 929 else assert(false); 930 } 931 else 932 { 933 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::StoreSubVector, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T}; 934 auto target = ::context->getConstantUndef(Ice::IceType_i32); 935 auto store = Ice::InstIntrinsicCall::create(::function, 3, nullptr, target, intrinsic); 936 store->addArg(value); 937 store->addArg(ptr); 938 store->addArg(::context->getConstantInt32(typeSize(type))); 939 ::basicBlock->appendInst(store); 940 } 941 } 942 else 943 { 944 assert(value->getType() == T(type)); 945 946 auto store = Ice::InstStore::create(::function, value, ptr, align); 947 ::basicBlock->appendInst(store); 948 } 949 950 return value; 951 } 952 953 Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex) 954 { 955 assert(index->getType() == Ice::IceType_i32); 956 957 if(auto *constant = llvm::dyn_cast<Ice::ConstantInteger32>(index)) 958 { 959 int32_t offset = constant->getValue() * (int)typeSize(type); 960 961 if(offset == 0) 962 { 963 return ptr; 964 } 965 966 return createAdd(ptr, createConstantInt(offset)); 967 } 968 969 if(!Ice::isByteSizedType(T(type))) 970 { 971 index = createMul(index, createConstantInt((int)typeSize(type))); 972 } 973 974 if(sizeof(void*) == 8) 975 { 976 if(unsignedIndex) 977 { 978 index = createZExt(index, T(Ice::IceType_i64)); 979 } 980 else 981 { 982 index = createSExt(index, T(Ice::IceType_i64)); 983 } 984 } 985 986 return createAdd(ptr, index); 987 } 988 989 Value *Nucleus::createAtomicAdd(Value *ptr, Value *value) 990 { 991 assert(false && "UNIMPLEMENTED"); return nullptr; 992 } 993 994 static Value *createCast(Ice::InstCast::OpKind op, Value *v, Type *destType) 995 { 996 if(v->getType() == T(destType)) 997 { 998 return v; 999 } 1000 1001 Ice::Variable *result = ::function->makeVariable(T(destType)); 1002 Ice::InstCast *cast = Ice::InstCast::create(::function, op, result, v); 1003 ::basicBlock->appendInst(cast); 1004 1005 return V(result); 1006 } 1007 1008 Value *Nucleus::createTrunc(Value *v, Type *destType) 1009 { 1010 return createCast(Ice::InstCast::Trunc, v, destType); 1011 } 1012 1013 Value *Nucleus::createZExt(Value *v, Type *destType) 1014 { 1015 return createCast(Ice::InstCast::Zext, v, destType); 1016 } 1017 1018 Value *Nucleus::createSExt(Value *v, Type *destType) 1019 { 1020 return createCast(Ice::InstCast::Sext, v, destType); 1021 } 1022 1023 Value *Nucleus::createFPToSI(Value *v, Type *destType) 1024 { 1025 return createCast(Ice::InstCast::Fptosi, v, destType); 1026 } 1027 1028 Value *Nucleus::createSIToFP(Value *v, Type *destType) 1029 { 1030 return createCast(Ice::InstCast::Sitofp, v, destType); 1031 } 1032 1033 Value *Nucleus::createFPTrunc(Value *v, Type *destType) 1034 { 1035 return createCast(Ice::InstCast::Fptrunc, v, destType); 1036 } 1037 1038 Value *Nucleus::createFPExt(Value *v, Type *destType) 1039 { 1040 return createCast(Ice::InstCast::Fpext, v, destType); 1041 } 1042 1043 Value *Nucleus::createBitCast(Value *v, Type *destType) 1044 { 1045 // Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need 1046 // support for casting between scalars and wide vectors. For platforms where this is not supported, 1047 // emulate them by writing to the stack and reading back as the destination type. 1048 if(emulateMismatchedBitCast) 1049 { 1050 if(!Ice::isVectorType(v->getType()) && Ice::isVectorType(T(destType))) 1051 { 1052 Value *address = allocateStackVariable(destType); 1053 createStore(v, address, T(v->getType())); 1054 return createLoad(address, destType); 1055 } 1056 else if(Ice::isVectorType(v->getType()) && !Ice::isVectorType(T(destType))) 1057 { 1058 Value *address = allocateStackVariable(T(v->getType())); 1059 createStore(v, address, T(v->getType())); 1060 return createLoad(address, destType); 1061 } 1062 } 1063 1064 return createCast(Ice::InstCast::Bitcast, v, destType); 1065 } 1066 1067 static Value *createIntCompare(Ice::InstIcmp::ICond condition, Value *lhs, Value *rhs) 1068 { 1069 assert(lhs->getType() == rhs->getType()); 1070 1071 auto result = ::function->makeVariable(Ice::isScalarIntegerType(lhs->getType()) ? Ice::IceType_i1 : lhs->getType()); 1072 auto cmp = Ice::InstIcmp::create(::function, condition, result, lhs, rhs); 1073 ::basicBlock->appendInst(cmp); 1074 1075 return V(result); 1076 } 1077 1078 Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs) 1079 { 1080 return createIntCompare(Ice::InstIcmp::Eq, lhs, rhs); 1081 } 1082 1083 Value *Nucleus::createICmpNE(Value *lhs, Value *rhs) 1084 { 1085 return createIntCompare(Ice::InstIcmp::Ne, lhs, rhs); 1086 } 1087 1088 Value *Nucleus::createICmpUGT(Value *lhs, Value *rhs) 1089 { 1090 return createIntCompare(Ice::InstIcmp::Ugt, lhs, rhs); 1091 } 1092 1093 Value *Nucleus::createICmpUGE(Value *lhs, Value *rhs) 1094 { 1095 return createIntCompare(Ice::InstIcmp::Uge, lhs, rhs); 1096 } 1097 1098 Value *Nucleus::createICmpULT(Value *lhs, Value *rhs) 1099 { 1100 return createIntCompare(Ice::InstIcmp::Ult, lhs, rhs); 1101 } 1102 1103 Value *Nucleus::createICmpULE(Value *lhs, Value *rhs) 1104 { 1105 return createIntCompare(Ice::InstIcmp::Ule, lhs, rhs); 1106 } 1107 1108 Value *Nucleus::createICmpSGT(Value *lhs, Value *rhs) 1109 { 1110 return createIntCompare(Ice::InstIcmp::Sgt, lhs, rhs); 1111 } 1112 1113 Value *Nucleus::createICmpSGE(Value *lhs, Value *rhs) 1114 { 1115 return createIntCompare(Ice::InstIcmp::Sge, lhs, rhs); 1116 } 1117 1118 Value *Nucleus::createICmpSLT(Value *lhs, Value *rhs) 1119 { 1120 return createIntCompare(Ice::InstIcmp::Slt, lhs, rhs); 1121 } 1122 1123 Value *Nucleus::createICmpSLE(Value *lhs, Value *rhs) 1124 { 1125 return createIntCompare(Ice::InstIcmp::Sle, lhs, rhs); 1126 } 1127 1128 static Value *createFloatCompare(Ice::InstFcmp::FCond condition, Value *lhs, Value *rhs) 1129 { 1130 assert(lhs->getType() == rhs->getType()); 1131 assert(Ice::isScalarFloatingType(lhs->getType()) || lhs->getType() == Ice::IceType_v4f32); 1132 1133 auto result = ::function->makeVariable(Ice::isScalarFloatingType(lhs->getType()) ? Ice::IceType_i1 : Ice::IceType_v4i32); 1134 auto cmp = Ice::InstFcmp::create(::function, condition, result, lhs, rhs); 1135 ::basicBlock->appendInst(cmp); 1136 1137 return V(result); 1138 } 1139 1140 Value *Nucleus::createFCmpOEQ(Value *lhs, Value *rhs) 1141 { 1142 return createFloatCompare(Ice::InstFcmp::Oeq, lhs, rhs); 1143 } 1144 1145 Value *Nucleus::createFCmpOGT(Value *lhs, Value *rhs) 1146 { 1147 return createFloatCompare(Ice::InstFcmp::Ogt, lhs, rhs); 1148 } 1149 1150 Value *Nucleus::createFCmpOGE(Value *lhs, Value *rhs) 1151 { 1152 return createFloatCompare(Ice::InstFcmp::Oge, lhs, rhs); 1153 } 1154 1155 Value *Nucleus::createFCmpOLT(Value *lhs, Value *rhs) 1156 { 1157 return createFloatCompare(Ice::InstFcmp::Olt, lhs, rhs); 1158 } 1159 1160 Value *Nucleus::createFCmpOLE(Value *lhs, Value *rhs) 1161 { 1162 return createFloatCompare(Ice::InstFcmp::Ole, lhs, rhs); 1163 } 1164 1165 Value *Nucleus::createFCmpONE(Value *lhs, Value *rhs) 1166 { 1167 return createFloatCompare(Ice::InstFcmp::One, lhs, rhs); 1168 } 1169 1170 Value *Nucleus::createFCmpORD(Value *lhs, Value *rhs) 1171 { 1172 return createFloatCompare(Ice::InstFcmp::Ord, lhs, rhs); 1173 } 1174 1175 Value *Nucleus::createFCmpUNO(Value *lhs, Value *rhs) 1176 { 1177 return createFloatCompare(Ice::InstFcmp::Uno, lhs, rhs); 1178 } 1179 1180 Value *Nucleus::createFCmpUEQ(Value *lhs, Value *rhs) 1181 { 1182 return createFloatCompare(Ice::InstFcmp::Ueq, lhs, rhs); 1183 } 1184 1185 Value *Nucleus::createFCmpUGT(Value *lhs, Value *rhs) 1186 { 1187 return createFloatCompare(Ice::InstFcmp::Ugt, lhs, rhs); 1188 } 1189 1190 Value *Nucleus::createFCmpUGE(Value *lhs, Value *rhs) 1191 { 1192 return createFloatCompare(Ice::InstFcmp::Uge, lhs, rhs); 1193 } 1194 1195 Value *Nucleus::createFCmpULT(Value *lhs, Value *rhs) 1196 { 1197 return createFloatCompare(Ice::InstFcmp::Ult, lhs, rhs); 1198 } 1199 1200 Value *Nucleus::createFCmpULE(Value *lhs, Value *rhs) 1201 { 1202 return createFloatCompare(Ice::InstFcmp::Ule, lhs, rhs); 1203 } 1204 1205 Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs) 1206 { 1207 return createFloatCompare(Ice::InstFcmp::Une, lhs, rhs); 1208 } 1209 1210 Value *Nucleus::createExtractElement(Value *vector, Type *type, int index) 1211 { 1212 auto result = ::function->makeVariable(T(type)); 1213 auto extract = Ice::InstExtractElement::create(::function, result, vector, ::context->getConstantInt32(index)); 1214 ::basicBlock->appendInst(extract); 1215 1216 return V(result); 1217 } 1218 1219 Value *Nucleus::createInsertElement(Value *vector, Value *element, int index) 1220 { 1221 auto result = ::function->makeVariable(vector->getType()); 1222 auto insert = Ice::InstInsertElement::create(::function, result, vector, element, ::context->getConstantInt32(index)); 1223 ::basicBlock->appendInst(insert); 1224 1225 return V(result); 1226 } 1227 1228 Value *Nucleus::createShuffleVector(Value *V1, Value *V2, const int *select) 1229 { 1230 assert(V1->getType() == V2->getType()); 1231 1232 int size = Ice::typeNumElements(V1->getType()); 1233 auto result = ::function->makeVariable(V1->getType()); 1234 auto shuffle = Ice::InstShuffleVector::create(::function, result, V1, V2); 1235 1236 for(int i = 0; i < size; i++) 1237 { 1238 shuffle->addIndex(llvm::cast<Ice::ConstantInteger32>(::context->getConstantInt32(select[i]))); 1239 } 1240 1241 ::basicBlock->appendInst(shuffle); 1242 1243 return V(result); 1244 } 1245 1246 Value *Nucleus::createSelect(Value *C, Value *ifTrue, Value *ifFalse) 1247 { 1248 assert(ifTrue->getType() == ifFalse->getType()); 1249 1250 auto result = ::function->makeVariable(ifTrue->getType()); 1251 auto *select = Ice::InstSelect::create(::function, result, C, ifTrue, ifFalse); 1252 ::basicBlock->appendInst(select); 1253 1254 return V(result); 1255 } 1256 1257 SwitchCases *Nucleus::createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases) 1258 { 1259 auto switchInst = Ice::InstSwitch::create(::function, numCases, control, defaultBranch); 1260 ::basicBlock->appendInst(switchInst); 1261 1262 return reinterpret_cast<SwitchCases*>(switchInst); 1263 } 1264 1265 void Nucleus::addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch) 1266 { 1267 switchCases->addBranch(label, label, branch); 1268 } 1269 1270 void Nucleus::createUnreachable() 1271 { 1272 Ice::InstUnreachable *unreachable = Ice::InstUnreachable::create(::function); 1273 ::basicBlock->appendInst(unreachable); 1274 } 1275 1276 static Value *createSwizzle4(Value *val, unsigned char select) 1277 { 1278 int swizzle[4] = 1279 { 1280 (select >> 0) & 0x03, 1281 (select >> 2) & 0x03, 1282 (select >> 4) & 0x03, 1283 (select >> 6) & 0x03, 1284 }; 1285 1286 return Nucleus::createShuffleVector(val, val, swizzle); 1287 } 1288 1289 static Value *createMask4(Value *lhs, Value *rhs, unsigned char select) 1290 { 1291 int64_t mask[4] = {0, 0, 0, 0}; 1292 1293 mask[(select >> 0) & 0x03] = -1; 1294 mask[(select >> 2) & 0x03] = -1; 1295 mask[(select >> 4) & 0x03] = -1; 1296 mask[(select >> 6) & 0x03] = -1; 1297 1298 Value *condition = Nucleus::createConstantVector(mask, T(Ice::IceType_v4i1)); 1299 Value *result = Nucleus::createSelect(condition, rhs, lhs); 1300 1301 return result; 1302 } 1303 1304 Type *Nucleus::getPointerType(Type *ElementType) 1305 { 1306 if(sizeof(void*) == 8) 1307 { 1308 return T(Ice::IceType_i64); 1309 } 1310 else 1311 { 1312 return T(Ice::IceType_i32); 1313 } 1314 } 1315 1316 Value *Nucleus::createNullValue(Type *Ty) 1317 { 1318 if(Ice::isVectorType(T(Ty))) 1319 { 1320 assert(Ice::typeNumElements(T(Ty)) <= 16); 1321 int64_t c[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1322 return createConstantVector(c, Ty); 1323 } 1324 else 1325 { 1326 return V(::context->getConstantZero(T(Ty))); 1327 } 1328 } 1329 1330 Value *Nucleus::createConstantLong(int64_t i) 1331 { 1332 return V(::context->getConstantInt64(i)); 1333 } 1334 1335 Value *Nucleus::createConstantInt(int i) 1336 { 1337 return V(::context->getConstantInt32(i)); 1338 } 1339 1340 Value *Nucleus::createConstantInt(unsigned int i) 1341 { 1342 return V(::context->getConstantInt32(i)); 1343 } 1344 1345 Value *Nucleus::createConstantBool(bool b) 1346 { 1347 return V(::context->getConstantInt1(b)); 1348 } 1349 1350 Value *Nucleus::createConstantByte(signed char i) 1351 { 1352 return V(::context->getConstantInt8(i)); 1353 } 1354 1355 Value *Nucleus::createConstantByte(unsigned char i) 1356 { 1357 return V(::context->getConstantInt8(i)); 1358 } 1359 1360 Value *Nucleus::createConstantShort(short i) 1361 { 1362 return V(::context->getConstantInt16(i)); 1363 } 1364 1365 Value *Nucleus::createConstantShort(unsigned short i) 1366 { 1367 return V(::context->getConstantInt16(i)); 1368 } 1369 1370 Value *Nucleus::createConstantFloat(float x) 1371 { 1372 return V(::context->getConstantFloat(x)); 1373 } 1374 1375 Value *Nucleus::createNullPointer(Type *Ty) 1376 { 1377 return createNullValue(T(sizeof(void*) == 8 ? Ice::IceType_i64 : Ice::IceType_i32)); 1378 } 1379 1380 Value *Nucleus::createConstantVector(const int64_t *constants, Type *type) 1381 { 1382 const int vectorSize = 16; 1383 assert(Ice::typeWidthInBytes(T(type)) == vectorSize); 1384 const int alignment = vectorSize; 1385 auto globalPool = ::function->getGlobalPool(); 1386 1387 const int64_t *i = constants; 1388 const double *f = reinterpret_cast<const double*>(constants); 1389 Ice::VariableDeclaration::DataInitializer *dataInitializer = nullptr; 1390 1391 switch((int)reinterpret_cast<intptr_t>(type)) 1392 { 1393 case Ice::IceType_v4i32: 1394 case Ice::IceType_v4i1: 1395 { 1396 const int initializer[4] = {(int)i[0], (int)i[1], (int)i[2], (int)i[3]}; 1397 static_assert(sizeof(initializer) == vectorSize, "!"); 1398 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1399 } 1400 break; 1401 case Ice::IceType_v4f32: 1402 { 1403 const float initializer[4] = {(float)f[0], (float)f[1], (float)f[2], (float)f[3]}; 1404 static_assert(sizeof(initializer) == vectorSize, "!"); 1405 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1406 } 1407 break; 1408 case Ice::IceType_v8i16: 1409 case Ice::IceType_v8i1: 1410 { 1411 const short initializer[8] = {(short)i[0], (short)i[1], (short)i[2], (short)i[3], (short)i[4], (short)i[5], (short)i[6], (short)i[7]}; 1412 static_assert(sizeof(initializer) == vectorSize, "!"); 1413 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1414 } 1415 break; 1416 case Ice::IceType_v16i8: 1417 case Ice::IceType_v16i1: 1418 { 1419 const char initializer[16] = {(char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[4], (char)i[5], (char)i[6], (char)i[7], (char)i[8], (char)i[9], (char)i[10], (char)i[11], (char)i[12], (char)i[13], (char)i[14], (char)i[15]}; 1420 static_assert(sizeof(initializer) == vectorSize, "!"); 1421 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1422 } 1423 break; 1424 case Type_v2i32: 1425 { 1426 const int initializer[4] = {(int)i[0], (int)i[1], (int)i[0], (int)i[1]}; 1427 static_assert(sizeof(initializer) == vectorSize, "!"); 1428 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1429 } 1430 break; 1431 case Type_v2f32: 1432 { 1433 const float initializer[4] = {(float)f[0], (float)f[1], (float)f[0], (float)f[1]}; 1434 static_assert(sizeof(initializer) == vectorSize, "!"); 1435 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1436 } 1437 break; 1438 case Type_v4i16: 1439 { 1440 const short initializer[8] = {(short)i[0], (short)i[1], (short)i[2], (short)i[3], (short)i[0], (short)i[1], (short)i[2], (short)i[3]}; 1441 static_assert(sizeof(initializer) == vectorSize, "!"); 1442 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1443 } 1444 break; 1445 case Type_v8i8: 1446 { 1447 const char initializer[16] = {(char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[4], (char)i[5], (char)i[6], (char)i[7], (char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[4], (char)i[5], (char)i[6], (char)i[7]}; 1448 static_assert(sizeof(initializer) == vectorSize, "!"); 1449 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1450 } 1451 break; 1452 case Type_v4i8: 1453 { 1454 const char initializer[16] = {(char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[0], (char)i[1], (char)i[2], (char)i[3], (char)i[0], (char)i[1], (char)i[2], (char)i[3]}; 1455 static_assert(sizeof(initializer) == vectorSize, "!"); 1456 dataInitializer = Ice::VariableDeclaration::DataInitializer::create(globalPool, (const char*)initializer, vectorSize); 1457 } 1458 break; 1459 default: 1460 assert(false && "Unknown constant vector type" && type); 1461 } 1462 1463 auto name = Ice::GlobalString::createWithoutString(::context); 1464 auto *variableDeclaration = Ice::VariableDeclaration::create(globalPool); 1465 variableDeclaration->setName(name); 1466 variableDeclaration->setAlignment(alignment); 1467 variableDeclaration->setIsConstant(true); 1468 variableDeclaration->addInitializer(dataInitializer); 1469 1470 ::function->addGlobal(variableDeclaration); 1471 1472 constexpr int32_t offset = 0; 1473 Ice::Operand *ptr = ::context->getConstantSym(offset, name); 1474 1475 Ice::Variable *result = ::function->makeVariable(T(type)); 1476 auto load = Ice::InstLoad::create(::function, result, ptr, alignment); 1477 ::basicBlock->appendInst(load); 1478 1479 return V(result); 1480 } 1481 1482 Value *Nucleus::createConstantVector(const double *constants, Type *type) 1483 { 1484 return createConstantVector((const int64_t*)constants, type); 1485 } 1486 1487 Type *Void::getType() 1488 { 1489 return T(Ice::IceType_void); 1490 } 1491 1492 Bool::Bool(Argument<Bool> argument) 1493 { 1494 storeValue(argument.value); 1495 } 1496 1497 Bool::Bool(bool x) 1498 { 1499 storeValue(Nucleus::createConstantBool(x)); 1500 } 1501 1502 Bool::Bool(RValue<Bool> rhs) 1503 { 1504 storeValue(rhs.value); 1505 } 1506 1507 Bool::Bool(const Bool &rhs) 1508 { 1509 Value *value = rhs.loadValue(); 1510 storeValue(value); 1511 } 1512 1513 Bool::Bool(const Reference<Bool> &rhs) 1514 { 1515 Value *value = rhs.loadValue(); 1516 storeValue(value); 1517 } 1518 1519 RValue<Bool> Bool::operator=(RValue<Bool> rhs) 1520 { 1521 storeValue(rhs.value); 1522 1523 return rhs; 1524 } 1525 1526 RValue<Bool> Bool::operator=(const Bool &rhs) 1527 { 1528 Value *value = rhs.loadValue(); 1529 storeValue(value); 1530 1531 return RValue<Bool>(value); 1532 } 1533 1534 RValue<Bool> Bool::operator=(const Reference<Bool> &rhs) 1535 { 1536 Value *value = rhs.loadValue(); 1537 storeValue(value); 1538 1539 return RValue<Bool>(value); 1540 } 1541 1542 RValue<Bool> operator!(RValue<Bool> val) 1543 { 1544 return RValue<Bool>(Nucleus::createNot(val.value)); 1545 } 1546 1547 RValue<Bool> operator&&(RValue<Bool> lhs, RValue<Bool> rhs) 1548 { 1549 return RValue<Bool>(Nucleus::createAnd(lhs.value, rhs.value)); 1550 } 1551 1552 RValue<Bool> operator||(RValue<Bool> lhs, RValue<Bool> rhs) 1553 { 1554 return RValue<Bool>(Nucleus::createOr(lhs.value, rhs.value)); 1555 } 1556 1557 Type *Bool::getType() 1558 { 1559 return T(Ice::IceType_i1); 1560 } 1561 1562 Byte::Byte(Argument<Byte> argument) 1563 { 1564 storeValue(argument.value); 1565 } 1566 1567 Byte::Byte(RValue<Int> cast) 1568 { 1569 Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); 1570 1571 storeValue(integer); 1572 } 1573 1574 Byte::Byte(RValue<UInt> cast) 1575 { 1576 Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); 1577 1578 storeValue(integer); 1579 } 1580 1581 Byte::Byte(RValue<UShort> cast) 1582 { 1583 Value *integer = Nucleus::createTrunc(cast.value, Byte::getType()); 1584 1585 storeValue(integer); 1586 } 1587 1588 Byte::Byte(int x) 1589 { 1590 storeValue(Nucleus::createConstantByte((unsigned char)x)); 1591 } 1592 1593 Byte::Byte(unsigned char x) 1594 { 1595 storeValue(Nucleus::createConstantByte(x)); 1596 } 1597 1598 Byte::Byte(RValue<Byte> rhs) 1599 { 1600 storeValue(rhs.value); 1601 } 1602 1603 Byte::Byte(const Byte &rhs) 1604 { 1605 Value *value = rhs.loadValue(); 1606 storeValue(value); 1607 } 1608 1609 Byte::Byte(const Reference<Byte> &rhs) 1610 { 1611 Value *value = rhs.loadValue(); 1612 storeValue(value); 1613 } 1614 1615 RValue<Byte> Byte::operator=(RValue<Byte> rhs) 1616 { 1617 storeValue(rhs.value); 1618 1619 return rhs; 1620 } 1621 1622 RValue<Byte> Byte::operator=(const Byte &rhs) 1623 { 1624 Value *value = rhs.loadValue(); 1625 storeValue(value); 1626 1627 return RValue<Byte>(value); 1628 } 1629 1630 RValue<Byte> Byte::operator=(const Reference<Byte> &rhs) 1631 { 1632 Value *value = rhs.loadValue(); 1633 storeValue(value); 1634 1635 return RValue<Byte>(value); 1636 } 1637 1638 RValue<Byte> operator+(RValue<Byte> lhs, RValue<Byte> rhs) 1639 { 1640 return RValue<Byte>(Nucleus::createAdd(lhs.value, rhs.value)); 1641 } 1642 1643 RValue<Byte> operator-(RValue<Byte> lhs, RValue<Byte> rhs) 1644 { 1645 return RValue<Byte>(Nucleus::createSub(lhs.value, rhs.value)); 1646 } 1647 1648 RValue<Byte> operator*(RValue<Byte> lhs, RValue<Byte> rhs) 1649 { 1650 return RValue<Byte>(Nucleus::createMul(lhs.value, rhs.value)); 1651 } 1652 1653 RValue<Byte> operator/(RValue<Byte> lhs, RValue<Byte> rhs) 1654 { 1655 return RValue<Byte>(Nucleus::createUDiv(lhs.value, rhs.value)); 1656 } 1657 1658 RValue<Byte> operator%(RValue<Byte> lhs, RValue<Byte> rhs) 1659 { 1660 return RValue<Byte>(Nucleus::createURem(lhs.value, rhs.value)); 1661 } 1662 1663 RValue<Byte> operator&(RValue<Byte> lhs, RValue<Byte> rhs) 1664 { 1665 return RValue<Byte>(Nucleus::createAnd(lhs.value, rhs.value)); 1666 } 1667 1668 RValue<Byte> operator|(RValue<Byte> lhs, RValue<Byte> rhs) 1669 { 1670 return RValue<Byte>(Nucleus::createOr(lhs.value, rhs.value)); 1671 } 1672 1673 RValue<Byte> operator^(RValue<Byte> lhs, RValue<Byte> rhs) 1674 { 1675 return RValue<Byte>(Nucleus::createXor(lhs.value, rhs.value)); 1676 } 1677 1678 RValue<Byte> operator<<(RValue<Byte> lhs, RValue<Byte> rhs) 1679 { 1680 return RValue<Byte>(Nucleus::createShl(lhs.value, rhs.value)); 1681 } 1682 1683 RValue<Byte> operator>>(RValue<Byte> lhs, RValue<Byte> rhs) 1684 { 1685 return RValue<Byte>(Nucleus::createLShr(lhs.value, rhs.value)); 1686 } 1687 1688 RValue<Byte> operator+=(Byte &lhs, RValue<Byte> rhs) 1689 { 1690 return lhs = lhs + rhs; 1691 } 1692 1693 RValue<Byte> operator-=(Byte &lhs, RValue<Byte> rhs) 1694 { 1695 return lhs = lhs - rhs; 1696 } 1697 1698 RValue<Byte> operator*=(Byte &lhs, RValue<Byte> rhs) 1699 { 1700 return lhs = lhs * rhs; 1701 } 1702 1703 RValue<Byte> operator/=(Byte &lhs, RValue<Byte> rhs) 1704 { 1705 return lhs = lhs / rhs; 1706 } 1707 1708 RValue<Byte> operator%=(Byte &lhs, RValue<Byte> rhs) 1709 { 1710 return lhs = lhs % rhs; 1711 } 1712 1713 RValue<Byte> operator&=(Byte &lhs, RValue<Byte> rhs) 1714 { 1715 return lhs = lhs & rhs; 1716 } 1717 1718 RValue<Byte> operator|=(Byte &lhs, RValue<Byte> rhs) 1719 { 1720 return lhs = lhs | rhs; 1721 } 1722 1723 RValue<Byte> operator^=(Byte &lhs, RValue<Byte> rhs) 1724 { 1725 return lhs = lhs ^ rhs; 1726 } 1727 1728 RValue<Byte> operator<<=(Byte &lhs, RValue<Byte> rhs) 1729 { 1730 return lhs = lhs << rhs; 1731 } 1732 1733 RValue<Byte> operator>>=(Byte &lhs, RValue<Byte> rhs) 1734 { 1735 return lhs = lhs >> rhs; 1736 } 1737 1738 RValue<Byte> operator+(RValue<Byte> val) 1739 { 1740 return val; 1741 } 1742 1743 RValue<Byte> operator-(RValue<Byte> val) 1744 { 1745 return RValue<Byte>(Nucleus::createNeg(val.value)); 1746 } 1747 1748 RValue<Byte> operator~(RValue<Byte> val) 1749 { 1750 return RValue<Byte>(Nucleus::createNot(val.value)); 1751 } 1752 1753 RValue<Byte> operator++(Byte &val, int) // Post-increment 1754 { 1755 RValue<Byte> res = val; 1756 val += Byte(1); 1757 return res; 1758 } 1759 1760 const Byte &operator++(Byte &val) // Pre-increment 1761 { 1762 val += Byte(1); 1763 return val; 1764 } 1765 1766 RValue<Byte> operator--(Byte &val, int) // Post-decrement 1767 { 1768 RValue<Byte> res = val; 1769 val -= Byte(1); 1770 return res; 1771 } 1772 1773 const Byte &operator--(Byte &val) // Pre-decrement 1774 { 1775 val -= Byte(1); 1776 return val; 1777 } 1778 1779 RValue<Bool> operator<(RValue<Byte> lhs, RValue<Byte> rhs) 1780 { 1781 return RValue<Bool>(Nucleus::createICmpULT(lhs.value, rhs.value)); 1782 } 1783 1784 RValue<Bool> operator<=(RValue<Byte> lhs, RValue<Byte> rhs) 1785 { 1786 return RValue<Bool>(Nucleus::createICmpULE(lhs.value, rhs.value)); 1787 } 1788 1789 RValue<Bool> operator>(RValue<Byte> lhs, RValue<Byte> rhs) 1790 { 1791 return RValue<Bool>(Nucleus::createICmpUGT(lhs.value, rhs.value)); 1792 } 1793 1794 RValue<Bool> operator>=(RValue<Byte> lhs, RValue<Byte> rhs) 1795 { 1796 return RValue<Bool>(Nucleus::createICmpUGE(lhs.value, rhs.value)); 1797 } 1798 1799 RValue<Bool> operator!=(RValue<Byte> lhs, RValue<Byte> rhs) 1800 { 1801 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 1802 } 1803 1804 RValue<Bool> operator==(RValue<Byte> lhs, RValue<Byte> rhs) 1805 { 1806 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 1807 } 1808 1809 Type *Byte::getType() 1810 { 1811 return T(Ice::IceType_i8); 1812 } 1813 1814 SByte::SByte(Argument<SByte> argument) 1815 { 1816 storeValue(argument.value); 1817 } 1818 1819 SByte::SByte(RValue<Int> cast) 1820 { 1821 Value *integer = Nucleus::createTrunc(cast.value, SByte::getType()); 1822 1823 storeValue(integer); 1824 } 1825 1826 SByte::SByte(RValue<Short> cast) 1827 { 1828 Value *integer = Nucleus::createTrunc(cast.value, SByte::getType()); 1829 1830 storeValue(integer); 1831 } 1832 1833 SByte::SByte(signed char x) 1834 { 1835 storeValue(Nucleus::createConstantByte(x)); 1836 } 1837 1838 SByte::SByte(RValue<SByte> rhs) 1839 { 1840 storeValue(rhs.value); 1841 } 1842 1843 SByte::SByte(const SByte &rhs) 1844 { 1845 Value *value = rhs.loadValue(); 1846 storeValue(value); 1847 } 1848 1849 SByte::SByte(const Reference<SByte> &rhs) 1850 { 1851 Value *value = rhs.loadValue(); 1852 storeValue(value); 1853 } 1854 1855 RValue<SByte> SByte::operator=(RValue<SByte> rhs) 1856 { 1857 storeValue(rhs.value); 1858 1859 return rhs; 1860 } 1861 1862 RValue<SByte> SByte::operator=(const SByte &rhs) 1863 { 1864 Value *value = rhs.loadValue(); 1865 storeValue(value); 1866 1867 return RValue<SByte>(value); 1868 } 1869 1870 RValue<SByte> SByte::operator=(const Reference<SByte> &rhs) 1871 { 1872 Value *value = rhs.loadValue(); 1873 storeValue(value); 1874 1875 return RValue<SByte>(value); 1876 } 1877 1878 RValue<SByte> operator+(RValue<SByte> lhs, RValue<SByte> rhs) 1879 { 1880 return RValue<SByte>(Nucleus::createAdd(lhs.value, rhs.value)); 1881 } 1882 1883 RValue<SByte> operator-(RValue<SByte> lhs, RValue<SByte> rhs) 1884 { 1885 return RValue<SByte>(Nucleus::createSub(lhs.value, rhs.value)); 1886 } 1887 1888 RValue<SByte> operator*(RValue<SByte> lhs, RValue<SByte> rhs) 1889 { 1890 return RValue<SByte>(Nucleus::createMul(lhs.value, rhs.value)); 1891 } 1892 1893 RValue<SByte> operator/(RValue<SByte> lhs, RValue<SByte> rhs) 1894 { 1895 return RValue<SByte>(Nucleus::createSDiv(lhs.value, rhs.value)); 1896 } 1897 1898 RValue<SByte> operator%(RValue<SByte> lhs, RValue<SByte> rhs) 1899 { 1900 return RValue<SByte>(Nucleus::createSRem(lhs.value, rhs.value)); 1901 } 1902 1903 RValue<SByte> operator&(RValue<SByte> lhs, RValue<SByte> rhs) 1904 { 1905 return RValue<SByte>(Nucleus::createAnd(lhs.value, rhs.value)); 1906 } 1907 1908 RValue<SByte> operator|(RValue<SByte> lhs, RValue<SByte> rhs) 1909 { 1910 return RValue<SByte>(Nucleus::createOr(lhs.value, rhs.value)); 1911 } 1912 1913 RValue<SByte> operator^(RValue<SByte> lhs, RValue<SByte> rhs) 1914 { 1915 return RValue<SByte>(Nucleus::createXor(lhs.value, rhs.value)); 1916 } 1917 1918 RValue<SByte> operator<<(RValue<SByte> lhs, RValue<SByte> rhs) 1919 { 1920 return RValue<SByte>(Nucleus::createShl(lhs.value, rhs.value)); 1921 } 1922 1923 RValue<SByte> operator>>(RValue<SByte> lhs, RValue<SByte> rhs) 1924 { 1925 return RValue<SByte>(Nucleus::createAShr(lhs.value, rhs.value)); 1926 } 1927 1928 RValue<SByte> operator+=(SByte &lhs, RValue<SByte> rhs) 1929 { 1930 return lhs = lhs + rhs; 1931 } 1932 1933 RValue<SByte> operator-=(SByte &lhs, RValue<SByte> rhs) 1934 { 1935 return lhs = lhs - rhs; 1936 } 1937 1938 RValue<SByte> operator*=(SByte &lhs, RValue<SByte> rhs) 1939 { 1940 return lhs = lhs * rhs; 1941 } 1942 1943 RValue<SByte> operator/=(SByte &lhs, RValue<SByte> rhs) 1944 { 1945 return lhs = lhs / rhs; 1946 } 1947 1948 RValue<SByte> operator%=(SByte &lhs, RValue<SByte> rhs) 1949 { 1950 return lhs = lhs % rhs; 1951 } 1952 1953 RValue<SByte> operator&=(SByte &lhs, RValue<SByte> rhs) 1954 { 1955 return lhs = lhs & rhs; 1956 } 1957 1958 RValue<SByte> operator|=(SByte &lhs, RValue<SByte> rhs) 1959 { 1960 return lhs = lhs | rhs; 1961 } 1962 1963 RValue<SByte> operator^=(SByte &lhs, RValue<SByte> rhs) 1964 { 1965 return lhs = lhs ^ rhs; 1966 } 1967 1968 RValue<SByte> operator<<=(SByte &lhs, RValue<SByte> rhs) 1969 { 1970 return lhs = lhs << rhs; 1971 } 1972 1973 RValue<SByte> operator>>=(SByte &lhs, RValue<SByte> rhs) 1974 { 1975 return lhs = lhs >> rhs; 1976 } 1977 1978 RValue<SByte> operator+(RValue<SByte> val) 1979 { 1980 return val; 1981 } 1982 1983 RValue<SByte> operator-(RValue<SByte> val) 1984 { 1985 return RValue<SByte>(Nucleus::createNeg(val.value)); 1986 } 1987 1988 RValue<SByte> operator~(RValue<SByte> val) 1989 { 1990 return RValue<SByte>(Nucleus::createNot(val.value)); 1991 } 1992 1993 RValue<SByte> operator++(SByte &val, int) // Post-increment 1994 { 1995 RValue<SByte> res = val; 1996 val += SByte(1); 1997 return res; 1998 } 1999 2000 const SByte &operator++(SByte &val) // Pre-increment 2001 { 2002 val += SByte(1); 2003 return val; 2004 } 2005 2006 RValue<SByte> operator--(SByte &val, int) // Post-decrement 2007 { 2008 RValue<SByte> res = val; 2009 val -= SByte(1); 2010 return res; 2011 } 2012 2013 const SByte &operator--(SByte &val) // Pre-decrement 2014 { 2015 val -= SByte(1); 2016 return val; 2017 } 2018 2019 RValue<Bool> operator<(RValue<SByte> lhs, RValue<SByte> rhs) 2020 { 2021 return RValue<Bool>(Nucleus::createICmpSLT(lhs.value, rhs.value)); 2022 } 2023 2024 RValue<Bool> operator<=(RValue<SByte> lhs, RValue<SByte> rhs) 2025 { 2026 return RValue<Bool>(Nucleus::createICmpSLE(lhs.value, rhs.value)); 2027 } 2028 2029 RValue<Bool> operator>(RValue<SByte> lhs, RValue<SByte> rhs) 2030 { 2031 return RValue<Bool>(Nucleus::createICmpSGT(lhs.value, rhs.value)); 2032 } 2033 2034 RValue<Bool> operator>=(RValue<SByte> lhs, RValue<SByte> rhs) 2035 { 2036 return RValue<Bool>(Nucleus::createICmpSGE(lhs.value, rhs.value)); 2037 } 2038 2039 RValue<Bool> operator!=(RValue<SByte> lhs, RValue<SByte> rhs) 2040 { 2041 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 2042 } 2043 2044 RValue<Bool> operator==(RValue<SByte> lhs, RValue<SByte> rhs) 2045 { 2046 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 2047 } 2048 2049 Type *SByte::getType() 2050 { 2051 return T(Ice::IceType_i8); 2052 } 2053 2054 Short::Short(Argument<Short> argument) 2055 { 2056 storeValue(argument.value); 2057 } 2058 2059 Short::Short(RValue<Int> cast) 2060 { 2061 Value *integer = Nucleus::createTrunc(cast.value, Short::getType()); 2062 2063 storeValue(integer); 2064 } 2065 2066 Short::Short(short x) 2067 { 2068 storeValue(Nucleus::createConstantShort(x)); 2069 } 2070 2071 Short::Short(RValue<Short> rhs) 2072 { 2073 storeValue(rhs.value); 2074 } 2075 2076 Short::Short(const Short &rhs) 2077 { 2078 Value *value = rhs.loadValue(); 2079 storeValue(value); 2080 } 2081 2082 Short::Short(const Reference<Short> &rhs) 2083 { 2084 Value *value = rhs.loadValue(); 2085 storeValue(value); 2086 } 2087 2088 RValue<Short> Short::operator=(RValue<Short> rhs) 2089 { 2090 storeValue(rhs.value); 2091 2092 return rhs; 2093 } 2094 2095 RValue<Short> Short::operator=(const Short &rhs) 2096 { 2097 Value *value = rhs.loadValue(); 2098 storeValue(value); 2099 2100 return RValue<Short>(value); 2101 } 2102 2103 RValue<Short> Short::operator=(const Reference<Short> &rhs) 2104 { 2105 Value *value = rhs.loadValue(); 2106 storeValue(value); 2107 2108 return RValue<Short>(value); 2109 } 2110 2111 RValue<Short> operator+(RValue<Short> lhs, RValue<Short> rhs) 2112 { 2113 return RValue<Short>(Nucleus::createAdd(lhs.value, rhs.value)); 2114 } 2115 2116 RValue<Short> operator-(RValue<Short> lhs, RValue<Short> rhs) 2117 { 2118 return RValue<Short>(Nucleus::createSub(lhs.value, rhs.value)); 2119 } 2120 2121 RValue<Short> operator*(RValue<Short> lhs, RValue<Short> rhs) 2122 { 2123 return RValue<Short>(Nucleus::createMul(lhs.value, rhs.value)); 2124 } 2125 2126 RValue<Short> operator/(RValue<Short> lhs, RValue<Short> rhs) 2127 { 2128 return RValue<Short>(Nucleus::createSDiv(lhs.value, rhs.value)); 2129 } 2130 2131 RValue<Short> operator%(RValue<Short> lhs, RValue<Short> rhs) 2132 { 2133 return RValue<Short>(Nucleus::createSRem(lhs.value, rhs.value)); 2134 } 2135 2136 RValue<Short> operator&(RValue<Short> lhs, RValue<Short> rhs) 2137 { 2138 return RValue<Short>(Nucleus::createAnd(lhs.value, rhs.value)); 2139 } 2140 2141 RValue<Short> operator|(RValue<Short> lhs, RValue<Short> rhs) 2142 { 2143 return RValue<Short>(Nucleus::createOr(lhs.value, rhs.value)); 2144 } 2145 2146 RValue<Short> operator^(RValue<Short> lhs, RValue<Short> rhs) 2147 { 2148 return RValue<Short>(Nucleus::createXor(lhs.value, rhs.value)); 2149 } 2150 2151 RValue<Short> operator<<(RValue<Short> lhs, RValue<Short> rhs) 2152 { 2153 return RValue<Short>(Nucleus::createShl(lhs.value, rhs.value)); 2154 } 2155 2156 RValue<Short> operator>>(RValue<Short> lhs, RValue<Short> rhs) 2157 { 2158 return RValue<Short>(Nucleus::createAShr(lhs.value, rhs.value)); 2159 } 2160 2161 RValue<Short> operator+=(Short &lhs, RValue<Short> rhs) 2162 { 2163 return lhs = lhs + rhs; 2164 } 2165 2166 RValue<Short> operator-=(Short &lhs, RValue<Short> rhs) 2167 { 2168 return lhs = lhs - rhs; 2169 } 2170 2171 RValue<Short> operator*=(Short &lhs, RValue<Short> rhs) 2172 { 2173 return lhs = lhs * rhs; 2174 } 2175 2176 RValue<Short> operator/=(Short &lhs, RValue<Short> rhs) 2177 { 2178 return lhs = lhs / rhs; 2179 } 2180 2181 RValue<Short> operator%=(Short &lhs, RValue<Short> rhs) 2182 { 2183 return lhs = lhs % rhs; 2184 } 2185 2186 RValue<Short> operator&=(Short &lhs, RValue<Short> rhs) 2187 { 2188 return lhs = lhs & rhs; 2189 } 2190 2191 RValue<Short> operator|=(Short &lhs, RValue<Short> rhs) 2192 { 2193 return lhs = lhs | rhs; 2194 } 2195 2196 RValue<Short> operator^=(Short &lhs, RValue<Short> rhs) 2197 { 2198 return lhs = lhs ^ rhs; 2199 } 2200 2201 RValue<Short> operator<<=(Short &lhs, RValue<Short> rhs) 2202 { 2203 return lhs = lhs << rhs; 2204 } 2205 2206 RValue<Short> operator>>=(Short &lhs, RValue<Short> rhs) 2207 { 2208 return lhs = lhs >> rhs; 2209 } 2210 2211 RValue<Short> operator+(RValue<Short> val) 2212 { 2213 return val; 2214 } 2215 2216 RValue<Short> operator-(RValue<Short> val) 2217 { 2218 return RValue<Short>(Nucleus::createNeg(val.value)); 2219 } 2220 2221 RValue<Short> operator~(RValue<Short> val) 2222 { 2223 return RValue<Short>(Nucleus::createNot(val.value)); 2224 } 2225 2226 RValue<Short> operator++(Short &val, int) // Post-increment 2227 { 2228 RValue<Short> res = val; 2229 val += Short(1); 2230 return res; 2231 } 2232 2233 const Short &operator++(Short &val) // Pre-increment 2234 { 2235 val += Short(1); 2236 return val; 2237 } 2238 2239 RValue<Short> operator--(Short &val, int) // Post-decrement 2240 { 2241 RValue<Short> res = val; 2242 val -= Short(1); 2243 return res; 2244 } 2245 2246 const Short &operator--(Short &val) // Pre-decrement 2247 { 2248 val -= Short(1); 2249 return val; 2250 } 2251 2252 RValue<Bool> operator<(RValue<Short> lhs, RValue<Short> rhs) 2253 { 2254 return RValue<Bool>(Nucleus::createICmpSLT(lhs.value, rhs.value)); 2255 } 2256 2257 RValue<Bool> operator<=(RValue<Short> lhs, RValue<Short> rhs) 2258 { 2259 return RValue<Bool>(Nucleus::createICmpSLE(lhs.value, rhs.value)); 2260 } 2261 2262 RValue<Bool> operator>(RValue<Short> lhs, RValue<Short> rhs) 2263 { 2264 return RValue<Bool>(Nucleus::createICmpSGT(lhs.value, rhs.value)); 2265 } 2266 2267 RValue<Bool> operator>=(RValue<Short> lhs, RValue<Short> rhs) 2268 { 2269 return RValue<Bool>(Nucleus::createICmpSGE(lhs.value, rhs.value)); 2270 } 2271 2272 RValue<Bool> operator!=(RValue<Short> lhs, RValue<Short> rhs) 2273 { 2274 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 2275 } 2276 2277 RValue<Bool> operator==(RValue<Short> lhs, RValue<Short> rhs) 2278 { 2279 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 2280 } 2281 2282 Type *Short::getType() 2283 { 2284 return T(Ice::IceType_i16); 2285 } 2286 2287 UShort::UShort(Argument<UShort> argument) 2288 { 2289 storeValue(argument.value); 2290 } 2291 2292 UShort::UShort(RValue<UInt> cast) 2293 { 2294 Value *integer = Nucleus::createTrunc(cast.value, UShort::getType()); 2295 2296 storeValue(integer); 2297 } 2298 2299 UShort::UShort(RValue<Int> cast) 2300 { 2301 Value *integer = Nucleus::createTrunc(cast.value, UShort::getType()); 2302 2303 storeValue(integer); 2304 } 2305 2306 UShort::UShort(unsigned short x) 2307 { 2308 storeValue(Nucleus::createConstantShort(x)); 2309 } 2310 2311 UShort::UShort(RValue<UShort> rhs) 2312 { 2313 storeValue(rhs.value); 2314 } 2315 2316 UShort::UShort(const UShort &rhs) 2317 { 2318 Value *value = rhs.loadValue(); 2319 storeValue(value); 2320 } 2321 2322 UShort::UShort(const Reference<UShort> &rhs) 2323 { 2324 Value *value = rhs.loadValue(); 2325 storeValue(value); 2326 } 2327 2328 RValue<UShort> UShort::operator=(RValue<UShort> rhs) 2329 { 2330 storeValue(rhs.value); 2331 2332 return rhs; 2333 } 2334 2335 RValue<UShort> UShort::operator=(const UShort &rhs) 2336 { 2337 Value *value = rhs.loadValue(); 2338 storeValue(value); 2339 2340 return RValue<UShort>(value); 2341 } 2342 2343 RValue<UShort> UShort::operator=(const Reference<UShort> &rhs) 2344 { 2345 Value *value = rhs.loadValue(); 2346 storeValue(value); 2347 2348 return RValue<UShort>(value); 2349 } 2350 2351 RValue<UShort> operator+(RValue<UShort> lhs, RValue<UShort> rhs) 2352 { 2353 return RValue<UShort>(Nucleus::createAdd(lhs.value, rhs.value)); 2354 } 2355 2356 RValue<UShort> operator-(RValue<UShort> lhs, RValue<UShort> rhs) 2357 { 2358 return RValue<UShort>(Nucleus::createSub(lhs.value, rhs.value)); 2359 } 2360 2361 RValue<UShort> operator*(RValue<UShort> lhs, RValue<UShort> rhs) 2362 { 2363 return RValue<UShort>(Nucleus::createMul(lhs.value, rhs.value)); 2364 } 2365 2366 RValue<UShort> operator/(RValue<UShort> lhs, RValue<UShort> rhs) 2367 { 2368 return RValue<UShort>(Nucleus::createUDiv(lhs.value, rhs.value)); 2369 } 2370 2371 RValue<UShort> operator%(RValue<UShort> lhs, RValue<UShort> rhs) 2372 { 2373 return RValue<UShort>(Nucleus::createURem(lhs.value, rhs.value)); 2374 } 2375 2376 RValue<UShort> operator&(RValue<UShort> lhs, RValue<UShort> rhs) 2377 { 2378 return RValue<UShort>(Nucleus::createAnd(lhs.value, rhs.value)); 2379 } 2380 2381 RValue<UShort> operator|(RValue<UShort> lhs, RValue<UShort> rhs) 2382 { 2383 return RValue<UShort>(Nucleus::createOr(lhs.value, rhs.value)); 2384 } 2385 2386 RValue<UShort> operator^(RValue<UShort> lhs, RValue<UShort> rhs) 2387 { 2388 return RValue<UShort>(Nucleus::createXor(lhs.value, rhs.value)); 2389 } 2390 2391 RValue<UShort> operator<<(RValue<UShort> lhs, RValue<UShort> rhs) 2392 { 2393 return RValue<UShort>(Nucleus::createShl(lhs.value, rhs.value)); 2394 } 2395 2396 RValue<UShort> operator>>(RValue<UShort> lhs, RValue<UShort> rhs) 2397 { 2398 return RValue<UShort>(Nucleus::createLShr(lhs.value, rhs.value)); 2399 } 2400 2401 RValue<UShort> operator+=(UShort &lhs, RValue<UShort> rhs) 2402 { 2403 return lhs = lhs + rhs; 2404 } 2405 2406 RValue<UShort> operator-=(UShort &lhs, RValue<UShort> rhs) 2407 { 2408 return lhs = lhs - rhs; 2409 } 2410 2411 RValue<UShort> operator*=(UShort &lhs, RValue<UShort> rhs) 2412 { 2413 return lhs = lhs * rhs; 2414 } 2415 2416 RValue<UShort> operator/=(UShort &lhs, RValue<UShort> rhs) 2417 { 2418 return lhs = lhs / rhs; 2419 } 2420 2421 RValue<UShort> operator%=(UShort &lhs, RValue<UShort> rhs) 2422 { 2423 return lhs = lhs % rhs; 2424 } 2425 2426 RValue<UShort> operator&=(UShort &lhs, RValue<UShort> rhs) 2427 { 2428 return lhs = lhs & rhs; 2429 } 2430 2431 RValue<UShort> operator|=(UShort &lhs, RValue<UShort> rhs) 2432 { 2433 return lhs = lhs | rhs; 2434 } 2435 2436 RValue<UShort> operator^=(UShort &lhs, RValue<UShort> rhs) 2437 { 2438 return lhs = lhs ^ rhs; 2439 } 2440 2441 RValue<UShort> operator<<=(UShort &lhs, RValue<UShort> rhs) 2442 { 2443 return lhs = lhs << rhs; 2444 } 2445 2446 RValue<UShort> operator>>=(UShort &lhs, RValue<UShort> rhs) 2447 { 2448 return lhs = lhs >> rhs; 2449 } 2450 2451 RValue<UShort> operator+(RValue<UShort> val) 2452 { 2453 return val; 2454 } 2455 2456 RValue<UShort> operator-(RValue<UShort> val) 2457 { 2458 return RValue<UShort>(Nucleus::createNeg(val.value)); 2459 } 2460 2461 RValue<UShort> operator~(RValue<UShort> val) 2462 { 2463 return RValue<UShort>(Nucleus::createNot(val.value)); 2464 } 2465 2466 RValue<UShort> operator++(UShort &val, int) // Post-increment 2467 { 2468 RValue<UShort> res = val; 2469 val += UShort(1); 2470 return res; 2471 } 2472 2473 const UShort &operator++(UShort &val) // Pre-increment 2474 { 2475 val += UShort(1); 2476 return val; 2477 } 2478 2479 RValue<UShort> operator--(UShort &val, int) // Post-decrement 2480 { 2481 RValue<UShort> res = val; 2482 val -= UShort(1); 2483 return res; 2484 } 2485 2486 const UShort &operator--(UShort &val) // Pre-decrement 2487 { 2488 val -= UShort(1); 2489 return val; 2490 } 2491 2492 RValue<Bool> operator<(RValue<UShort> lhs, RValue<UShort> rhs) 2493 { 2494 return RValue<Bool>(Nucleus::createICmpULT(lhs.value, rhs.value)); 2495 } 2496 2497 RValue<Bool> operator<=(RValue<UShort> lhs, RValue<UShort> rhs) 2498 { 2499 return RValue<Bool>(Nucleus::createICmpULE(lhs.value, rhs.value)); 2500 } 2501 2502 RValue<Bool> operator>(RValue<UShort> lhs, RValue<UShort> rhs) 2503 { 2504 return RValue<Bool>(Nucleus::createICmpUGT(lhs.value, rhs.value)); 2505 } 2506 2507 RValue<Bool> operator>=(RValue<UShort> lhs, RValue<UShort> rhs) 2508 { 2509 return RValue<Bool>(Nucleus::createICmpUGE(lhs.value, rhs.value)); 2510 } 2511 2512 RValue<Bool> operator!=(RValue<UShort> lhs, RValue<UShort> rhs) 2513 { 2514 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 2515 } 2516 2517 RValue<Bool> operator==(RValue<UShort> lhs, RValue<UShort> rhs) 2518 { 2519 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 2520 } 2521 2522 Type *UShort::getType() 2523 { 2524 return T(Ice::IceType_i16); 2525 } 2526 2527 Byte4::Byte4(RValue<Byte8> cast) 2528 { 2529 storeValue(Nucleus::createBitCast(cast.value, getType())); 2530 } 2531 2532 Byte4::Byte4(const Reference<Byte4> &rhs) 2533 { 2534 Value *value = rhs.loadValue(); 2535 storeValue(value); 2536 } 2537 2538 Type *Byte4::getType() 2539 { 2540 return T(Type_v4i8); 2541 } 2542 2543 Type *SByte4::getType() 2544 { 2545 return T(Type_v4i8); 2546 } 2547 2548 Byte8::Byte8(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) 2549 { 2550 int64_t constantVector[8] = {x0, x1, x2, x3, x4, x5, x6, x7}; 2551 storeValue(Nucleus::createConstantVector(constantVector, getType())); 2552 } 2553 2554 Byte8::Byte8(RValue<Byte8> rhs) 2555 { 2556 storeValue(rhs.value); 2557 } 2558 2559 Byte8::Byte8(const Byte8 &rhs) 2560 { 2561 Value *value = rhs.loadValue(); 2562 storeValue(value); 2563 } 2564 2565 Byte8::Byte8(const Reference<Byte8> &rhs) 2566 { 2567 Value *value = rhs.loadValue(); 2568 storeValue(value); 2569 } 2570 2571 RValue<Byte8> Byte8::operator=(RValue<Byte8> rhs) 2572 { 2573 storeValue(rhs.value); 2574 2575 return rhs; 2576 } 2577 2578 RValue<Byte8> Byte8::operator=(const Byte8 &rhs) 2579 { 2580 Value *value = rhs.loadValue(); 2581 storeValue(value); 2582 2583 return RValue<Byte8>(value); 2584 } 2585 2586 RValue<Byte8> Byte8::operator=(const Reference<Byte8> &rhs) 2587 { 2588 Value *value = rhs.loadValue(); 2589 storeValue(value); 2590 2591 return RValue<Byte8>(value); 2592 } 2593 2594 RValue<Byte8> operator+(RValue<Byte8> lhs, RValue<Byte8> rhs) 2595 { 2596 return RValue<Byte8>(Nucleus::createAdd(lhs.value, rhs.value)); 2597 } 2598 2599 RValue<Byte8> operator-(RValue<Byte8> lhs, RValue<Byte8> rhs) 2600 { 2601 return RValue<Byte8>(Nucleus::createSub(lhs.value, rhs.value)); 2602 } 2603 2604 // RValue<Byte8> operator*(RValue<Byte8> lhs, RValue<Byte8> rhs) 2605 // { 2606 // return RValue<Byte8>(Nucleus::createMul(lhs.value, rhs.value)); 2607 // } 2608 2609 // RValue<Byte8> operator/(RValue<Byte8> lhs, RValue<Byte8> rhs) 2610 // { 2611 // return RValue<Byte8>(Nucleus::createUDiv(lhs.value, rhs.value)); 2612 // } 2613 2614 // RValue<Byte8> operator%(RValue<Byte8> lhs, RValue<Byte8> rhs) 2615 // { 2616 // return RValue<Byte8>(Nucleus::createURem(lhs.value, rhs.value)); 2617 // } 2618 2619 RValue<Byte8> operator&(RValue<Byte8> lhs, RValue<Byte8> rhs) 2620 { 2621 return RValue<Byte8>(Nucleus::createAnd(lhs.value, rhs.value)); 2622 } 2623 2624 RValue<Byte8> operator|(RValue<Byte8> lhs, RValue<Byte8> rhs) 2625 { 2626 return RValue<Byte8>(Nucleus::createOr(lhs.value, rhs.value)); 2627 } 2628 2629 RValue<Byte8> operator^(RValue<Byte8> lhs, RValue<Byte8> rhs) 2630 { 2631 return RValue<Byte8>(Nucleus::createXor(lhs.value, rhs.value)); 2632 } 2633 2634 // RValue<Byte8> operator<<(RValue<Byte8> lhs, unsigned char rhs) 2635 // { 2636 // return RValue<Byte8>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 2637 // } 2638 2639 // RValue<Byte8> operator>>(RValue<Byte8> lhs, unsigned char rhs) 2640 // { 2641 // return RValue<Byte8>(Nucleus::createLShr(lhs.value, V(::context->getConstantInt32(rhs)))); 2642 // } 2643 2644 RValue<Byte8> operator+=(Byte8 &lhs, RValue<Byte8> rhs) 2645 { 2646 return lhs = lhs + rhs; 2647 } 2648 2649 RValue<Byte8> operator-=(Byte8 &lhs, RValue<Byte8> rhs) 2650 { 2651 return lhs = lhs - rhs; 2652 } 2653 2654 // RValue<Byte8> operator*=(Byte8 &lhs, RValue<Byte8> rhs) 2655 // { 2656 // return lhs = lhs * rhs; 2657 // } 2658 2659 // RValue<Byte8> operator/=(Byte8 &lhs, RValue<Byte8> rhs) 2660 // { 2661 // return lhs = lhs / rhs; 2662 // } 2663 2664 // RValue<Byte8> operator%=(Byte8 &lhs, RValue<Byte8> rhs) 2665 // { 2666 // return lhs = lhs % rhs; 2667 // } 2668 2669 RValue<Byte8> operator&=(Byte8 &lhs, RValue<Byte8> rhs) 2670 { 2671 return lhs = lhs & rhs; 2672 } 2673 2674 RValue<Byte8> operator|=(Byte8 &lhs, RValue<Byte8> rhs) 2675 { 2676 return lhs = lhs | rhs; 2677 } 2678 2679 RValue<Byte8> operator^=(Byte8 &lhs, RValue<Byte8> rhs) 2680 { 2681 return lhs = lhs ^ rhs; 2682 } 2683 2684 // RValue<Byte8> operator<<=(Byte8 &lhs, RValue<Byte8> rhs) 2685 // { 2686 // return lhs = lhs << rhs; 2687 // } 2688 2689 // RValue<Byte8> operator>>=(Byte8 &lhs, RValue<Byte8> rhs) 2690 // { 2691 // return lhs = lhs >> rhs; 2692 // } 2693 2694 // RValue<Byte8> operator+(RValue<Byte8> val) 2695 // { 2696 // return val; 2697 // } 2698 2699 // RValue<Byte8> operator-(RValue<Byte8> val) 2700 // { 2701 // return RValue<Byte8>(Nucleus::createNeg(val.value)); 2702 // } 2703 2704 RValue<Byte8> operator~(RValue<Byte8> val) 2705 { 2706 return RValue<Byte8>(Nucleus::createNot(val.value)); 2707 } 2708 2709 RValue<Byte> Extract(RValue<Byte8> val, int i) 2710 { 2711 return RValue<Byte>(Nucleus::createExtractElement(val.value, Byte::getType(), i)); 2712 } 2713 2714 RValue<Byte8> Insert(RValue<Byte8> val, RValue<Byte> element, int i) 2715 { 2716 return RValue<Byte8>(Nucleus::createInsertElement(val.value, element.value, i)); 2717 } 2718 2719 RValue<Byte> SaturateUnsigned(RValue<Short> x) 2720 { 2721 return Byte(IfThenElse(Int(x) > 0xFF, Int(0xFF), IfThenElse(Int(x) < 0, Int(0), Int(x)))); 2722 } 2723 2724 RValue<Byte8> AddSat(RValue<Byte8> x, RValue<Byte8> y) 2725 { 2726 if(emulateIntrinsics) 2727 { 2728 Byte8 result; 2729 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 0)) + Int(Extract(y, 0)))), 0); 2730 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 1)) + Int(Extract(y, 1)))), 1); 2731 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 2)) + Int(Extract(y, 2)))), 2); 2732 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 3)) + Int(Extract(y, 3)))), 3); 2733 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 4)) + Int(Extract(y, 4)))), 4); 2734 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 5)) + Int(Extract(y, 5)))), 5); 2735 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 6)) + Int(Extract(y, 6)))), 6); 2736 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 7)) + Int(Extract(y, 7)))), 7); 2737 2738 return result; 2739 } 2740 else 2741 { 2742 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 2743 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::AddSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 2744 auto target = ::context->getConstantUndef(Ice::IceType_i32); 2745 auto paddusb = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 2746 paddusb->addArg(x.value); 2747 paddusb->addArg(y.value); 2748 ::basicBlock->appendInst(paddusb); 2749 2750 return RValue<Byte8>(V(result)); 2751 } 2752 } 2753 2754 RValue<Byte8> SubSat(RValue<Byte8> x, RValue<Byte8> y) 2755 { 2756 if(emulateIntrinsics) 2757 { 2758 Byte8 result; 2759 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 0)) - Int(Extract(y, 0)))), 0); 2760 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 1)) - Int(Extract(y, 1)))), 1); 2761 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 2)) - Int(Extract(y, 2)))), 2); 2762 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 3)) - Int(Extract(y, 3)))), 3); 2763 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 4)) - Int(Extract(y, 4)))), 4); 2764 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 5)) - Int(Extract(y, 5)))), 5); 2765 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 6)) - Int(Extract(y, 6)))), 6); 2766 result = Insert(result, SaturateUnsigned(Short(Int(Extract(x, 7)) - Int(Extract(y, 7)))), 7); 2767 2768 return result; 2769 } 2770 else 2771 { 2772 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 2773 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SubtractSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 2774 auto target = ::context->getConstantUndef(Ice::IceType_i32); 2775 auto psubusw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 2776 psubusw->addArg(x.value); 2777 psubusw->addArg(y.value); 2778 ::basicBlock->appendInst(psubusw); 2779 2780 return RValue<Byte8>(V(result)); 2781 } 2782 } 2783 2784 RValue<Short4> Unpack(RValue<Byte4> x) 2785 { 2786 int shuffle[16] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; // Real type is v16i8 2787 return As<Short4>(Nucleus::createShuffleVector(x.value, x.value, shuffle)); 2788 } 2789 2790 RValue<Short4> Unpack(RValue<Byte4> x, RValue<Byte4> y) 2791 { 2792 return UnpackLow(As<Byte8>(x), As<Byte8>(y)); 2793 } 2794 2795 RValue<Short4> UnpackLow(RValue<Byte8> x, RValue<Byte8> y) 2796 { 2797 int shuffle[16] = {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}; // Real type is v16i8 2798 return As<Short4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 2799 } 2800 2801 RValue<Short4> UnpackHigh(RValue<Byte8> x, RValue<Byte8> y) 2802 { 2803 int shuffle[16] = {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}; // Real type is v16i8 2804 auto lowHigh = RValue<Byte16>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 2805 return As<Short4>(Swizzle(As<Int4>(lowHigh), 0xEE)); 2806 } 2807 2808 RValue<SByte> Extract(RValue<SByte8> val, int i) 2809 { 2810 return RValue<SByte>(Nucleus::createExtractElement(val.value, SByte::getType(), i)); 2811 } 2812 2813 RValue<SByte8> Insert(RValue<SByte8> val, RValue<SByte> element, int i) 2814 { 2815 return RValue<SByte8>(Nucleus::createInsertElement(val.value, element.value, i)); 2816 } 2817 2818 RValue<SByte8> operator>>(RValue<SByte8> lhs, unsigned char rhs) 2819 { 2820 if(emulateIntrinsics) 2821 { 2822 SByte8 result; 2823 result = Insert(result, Extract(lhs, 0) >> SByte(rhs), 0); 2824 result = Insert(result, Extract(lhs, 1) >> SByte(rhs), 1); 2825 result = Insert(result, Extract(lhs, 2) >> SByte(rhs), 2); 2826 result = Insert(result, Extract(lhs, 3) >> SByte(rhs), 3); 2827 result = Insert(result, Extract(lhs, 4) >> SByte(rhs), 4); 2828 result = Insert(result, Extract(lhs, 5) >> SByte(rhs), 5); 2829 result = Insert(result, Extract(lhs, 6) >> SByte(rhs), 6); 2830 result = Insert(result, Extract(lhs, 7) >> SByte(rhs), 7); 2831 2832 return result; 2833 } 2834 else 2835 { 2836 #if defined(__i386__) || defined(__x86_64__) 2837 // SSE2 doesn't support byte vector shifts, so shift as shorts and recombine. 2838 RValue<Short4> hi = (As<Short4>(lhs) >> rhs) & Short4(0xFF00u); 2839 RValue<Short4> lo = As<Short4>(As<UShort4>((As<Short4>(lhs) << 8) >> rhs) >> 8); 2840 2841 return As<SByte8>(hi | lo); 2842 #else 2843 return RValue<SByte8>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 2844 #endif 2845 } 2846 } 2847 2848 RValue<Int> SignMask(RValue<Byte8> x) 2849 { 2850 if(emulateIntrinsics || CPUID::ARM) 2851 { 2852 Byte8 xx = As<Byte8>(As<SByte8>(x) >> 7) & Byte8(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80); 2853 return Int(Extract(xx, 0)) | Int(Extract(xx, 1)) | Int(Extract(xx, 2)) | Int(Extract(xx, 3)) | Int(Extract(xx, 4)) | Int(Extract(xx, 5)) | Int(Extract(xx, 6)) | Int(Extract(xx, 7)); 2854 } 2855 else 2856 { 2857 Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); 2858 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 2859 auto target = ::context->getConstantUndef(Ice::IceType_i32); 2860 auto movmsk = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 2861 movmsk->addArg(x.value); 2862 ::basicBlock->appendInst(movmsk); 2863 2864 return RValue<Int>(V(result)) & 0xFF; 2865 } 2866 } 2867 2868 // RValue<Byte8> CmpGT(RValue<Byte8> x, RValue<Byte8> y) 2869 // { 2870 // return RValue<Byte8>(createIntCompare(Ice::InstIcmp::Ugt, x.value, y.value)); 2871 // } 2872 2873 RValue<Byte8> CmpEQ(RValue<Byte8> x, RValue<Byte8> y) 2874 { 2875 return RValue<Byte8>(Nucleus::createICmpEQ(x.value, y.value)); 2876 } 2877 2878 Type *Byte8::getType() 2879 { 2880 return T(Type_v8i8); 2881 } 2882 2883 SByte8::SByte8(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) 2884 { 2885 int64_t constantVector[8] = { x0, x1, x2, x3, x4, x5, x6, x7 }; 2886 Value *vector = V(Nucleus::createConstantVector(constantVector, getType())); 2887 2888 storeValue(Nucleus::createBitCast(vector, getType())); 2889 } 2890 2891 SByte8::SByte8(RValue<SByte8> rhs) 2892 { 2893 storeValue(rhs.value); 2894 } 2895 2896 SByte8::SByte8(const SByte8 &rhs) 2897 { 2898 Value *value = rhs.loadValue(); 2899 storeValue(value); 2900 } 2901 2902 SByte8::SByte8(const Reference<SByte8> &rhs) 2903 { 2904 Value *value = rhs.loadValue(); 2905 storeValue(value); 2906 } 2907 2908 RValue<SByte8> SByte8::operator=(RValue<SByte8> rhs) 2909 { 2910 storeValue(rhs.value); 2911 2912 return rhs; 2913 } 2914 2915 RValue<SByte8> SByte8::operator=(const SByte8 &rhs) 2916 { 2917 Value *value = rhs.loadValue(); 2918 storeValue(value); 2919 2920 return RValue<SByte8>(value); 2921 } 2922 2923 RValue<SByte8> SByte8::operator=(const Reference<SByte8> &rhs) 2924 { 2925 Value *value = rhs.loadValue(); 2926 storeValue(value); 2927 2928 return RValue<SByte8>(value); 2929 } 2930 2931 RValue<SByte8> operator+(RValue<SByte8> lhs, RValue<SByte8> rhs) 2932 { 2933 return RValue<SByte8>(Nucleus::createAdd(lhs.value, rhs.value)); 2934 } 2935 2936 RValue<SByte8> operator-(RValue<SByte8> lhs, RValue<SByte8> rhs) 2937 { 2938 return RValue<SByte8>(Nucleus::createSub(lhs.value, rhs.value)); 2939 } 2940 2941 // RValue<SByte8> operator*(RValue<SByte8> lhs, RValue<SByte8> rhs) 2942 // { 2943 // return RValue<SByte8>(Nucleus::createMul(lhs.value, rhs.value)); 2944 // } 2945 2946 // RValue<SByte8> operator/(RValue<SByte8> lhs, RValue<SByte8> rhs) 2947 // { 2948 // return RValue<SByte8>(Nucleus::createSDiv(lhs.value, rhs.value)); 2949 // } 2950 2951 // RValue<SByte8> operator%(RValue<SByte8> lhs, RValue<SByte8> rhs) 2952 // { 2953 // return RValue<SByte8>(Nucleus::createSRem(lhs.value, rhs.value)); 2954 // } 2955 2956 RValue<SByte8> operator&(RValue<SByte8> lhs, RValue<SByte8> rhs) 2957 { 2958 return RValue<SByte8>(Nucleus::createAnd(lhs.value, rhs.value)); 2959 } 2960 2961 RValue<SByte8> operator|(RValue<SByte8> lhs, RValue<SByte8> rhs) 2962 { 2963 return RValue<SByte8>(Nucleus::createOr(lhs.value, rhs.value)); 2964 } 2965 2966 RValue<SByte8> operator^(RValue<SByte8> lhs, RValue<SByte8> rhs) 2967 { 2968 return RValue<SByte8>(Nucleus::createXor(lhs.value, rhs.value)); 2969 } 2970 2971 // RValue<SByte8> operator<<(RValue<SByte8> lhs, unsigned char rhs) 2972 // { 2973 // return RValue<SByte8>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 2974 // } 2975 2976 // RValue<SByte8> operator>>(RValue<SByte8> lhs, unsigned char rhs) 2977 // { 2978 // return RValue<SByte8>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 2979 // } 2980 2981 RValue<SByte8> operator+=(SByte8 &lhs, RValue<SByte8> rhs) 2982 { 2983 return lhs = lhs + rhs; 2984 } 2985 2986 RValue<SByte8> operator-=(SByte8 &lhs, RValue<SByte8> rhs) 2987 { 2988 return lhs = lhs - rhs; 2989 } 2990 2991 // RValue<SByte8> operator*=(SByte8 &lhs, RValue<SByte8> rhs) 2992 // { 2993 // return lhs = lhs * rhs; 2994 // } 2995 2996 // RValue<SByte8> operator/=(SByte8 &lhs, RValue<SByte8> rhs) 2997 // { 2998 // return lhs = lhs / rhs; 2999 // } 3000 3001 // RValue<SByte8> operator%=(SByte8 &lhs, RValue<SByte8> rhs) 3002 // { 3003 // return lhs = lhs % rhs; 3004 // } 3005 3006 RValue<SByte8> operator&=(SByte8 &lhs, RValue<SByte8> rhs) 3007 { 3008 return lhs = lhs & rhs; 3009 } 3010 3011 RValue<SByte8> operator|=(SByte8 &lhs, RValue<SByte8> rhs) 3012 { 3013 return lhs = lhs | rhs; 3014 } 3015 3016 RValue<SByte8> operator^=(SByte8 &lhs, RValue<SByte8> rhs) 3017 { 3018 return lhs = lhs ^ rhs; 3019 } 3020 3021 // RValue<SByte8> operator<<=(SByte8 &lhs, RValue<SByte8> rhs) 3022 // { 3023 // return lhs = lhs << rhs; 3024 // } 3025 3026 // RValue<SByte8> operator>>=(SByte8 &lhs, RValue<SByte8> rhs) 3027 // { 3028 // return lhs = lhs >> rhs; 3029 // } 3030 3031 // RValue<SByte8> operator+(RValue<SByte8> val) 3032 // { 3033 // return val; 3034 // } 3035 3036 // RValue<SByte8> operator-(RValue<SByte8> val) 3037 // { 3038 // return RValue<SByte8>(Nucleus::createNeg(val.value)); 3039 // } 3040 3041 RValue<SByte8> operator~(RValue<SByte8> val) 3042 { 3043 return RValue<SByte8>(Nucleus::createNot(val.value)); 3044 } 3045 3046 RValue<SByte> SaturateSigned(RValue<Short> x) 3047 { 3048 return SByte(IfThenElse(Int(x) > 0x7F, Int(0x7F), IfThenElse(Int(x) < -0x80, Int(0x80), Int(x)))); 3049 } 3050 3051 RValue<SByte8> AddSat(RValue<SByte8> x, RValue<SByte8> y) 3052 { 3053 if(emulateIntrinsics) 3054 { 3055 SByte8 result; 3056 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 0)) + Int(Extract(y, 0)))), 0); 3057 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 1)) + Int(Extract(y, 1)))), 1); 3058 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 2)) + Int(Extract(y, 2)))), 2); 3059 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 3)) + Int(Extract(y, 3)))), 3); 3060 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 4)) + Int(Extract(y, 4)))), 4); 3061 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 5)) + Int(Extract(y, 5)))), 5); 3062 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 6)) + Int(Extract(y, 6)))), 6); 3063 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 7)) + Int(Extract(y, 7)))), 7); 3064 3065 return result; 3066 } 3067 else 3068 { 3069 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 3070 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::AddSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3071 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3072 auto paddsb = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3073 paddsb->addArg(x.value); 3074 paddsb->addArg(y.value); 3075 ::basicBlock->appendInst(paddsb); 3076 3077 return RValue<SByte8>(V(result)); 3078 } 3079 } 3080 3081 RValue<SByte8> SubSat(RValue<SByte8> x, RValue<SByte8> y) 3082 { 3083 if(emulateIntrinsics) 3084 { 3085 SByte8 result; 3086 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 0)) - Int(Extract(y, 0)))), 0); 3087 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 1)) - Int(Extract(y, 1)))), 1); 3088 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 2)) - Int(Extract(y, 2)))), 2); 3089 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 3)) - Int(Extract(y, 3)))), 3); 3090 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 4)) - Int(Extract(y, 4)))), 4); 3091 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 5)) - Int(Extract(y, 5)))), 5); 3092 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 6)) - Int(Extract(y, 6)))), 6); 3093 result = Insert(result, SaturateSigned(Short(Int(Extract(x, 7)) - Int(Extract(y, 7)))), 7); 3094 3095 return result; 3096 } 3097 else 3098 { 3099 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 3100 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SubtractSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3101 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3102 auto psubsb = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3103 psubsb->addArg(x.value); 3104 psubsb->addArg(y.value); 3105 ::basicBlock->appendInst(psubsb); 3106 3107 return RValue<SByte8>(V(result)); 3108 } 3109 } 3110 3111 RValue<Short4> UnpackLow(RValue<SByte8> x, RValue<SByte8> y) 3112 { 3113 int shuffle[16] = {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}; // Real type is v16i8 3114 return As<Short4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 3115 } 3116 3117 RValue<Short4> UnpackHigh(RValue<SByte8> x, RValue<SByte8> y) 3118 { 3119 int shuffle[16] = {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}; // Real type is v16i8 3120 auto lowHigh = RValue<Byte16>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 3121 return As<Short4>(Swizzle(As<Int4>(lowHigh), 0xEE)); 3122 } 3123 3124 RValue<Int> SignMask(RValue<SByte8> x) 3125 { 3126 if(emulateIntrinsics || CPUID::ARM) 3127 { 3128 SByte8 xx = (x >> 7) & SByte8(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80); 3129 return Int(Extract(xx, 0)) | Int(Extract(xx, 1)) | Int(Extract(xx, 2)) | Int(Extract(xx, 3)) | Int(Extract(xx, 4)) | Int(Extract(xx, 5)) | Int(Extract(xx, 6)) | Int(Extract(xx, 7)); 3130 } 3131 else 3132 { 3133 Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); 3134 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3135 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3136 auto movmsk = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 3137 movmsk->addArg(x.value); 3138 ::basicBlock->appendInst(movmsk); 3139 3140 return RValue<Int>(V(result)) & 0xFF; 3141 } 3142 } 3143 3144 RValue<Byte8> CmpGT(RValue<SByte8> x, RValue<SByte8> y) 3145 { 3146 return RValue<Byte8>(createIntCompare(Ice::InstIcmp::Sgt, x.value, y.value)); 3147 } 3148 3149 RValue<Byte8> CmpEQ(RValue<SByte8> x, RValue<SByte8> y) 3150 { 3151 return RValue<Byte8>(Nucleus::createICmpEQ(x.value, y.value)); 3152 } 3153 3154 Type *SByte8::getType() 3155 { 3156 return T(Type_v8i8); 3157 } 3158 3159 Byte16::Byte16(RValue<Byte16> rhs) 3160 { 3161 storeValue(rhs.value); 3162 } 3163 3164 Byte16::Byte16(const Byte16 &rhs) 3165 { 3166 Value *value = rhs.loadValue(); 3167 storeValue(value); 3168 } 3169 3170 Byte16::Byte16(const Reference<Byte16> &rhs) 3171 { 3172 Value *value = rhs.loadValue(); 3173 storeValue(value); 3174 } 3175 3176 RValue<Byte16> Byte16::operator=(RValue<Byte16> rhs) 3177 { 3178 storeValue(rhs.value); 3179 3180 return rhs; 3181 } 3182 3183 RValue<Byte16> Byte16::operator=(const Byte16 &rhs) 3184 { 3185 Value *value = rhs.loadValue(); 3186 storeValue(value); 3187 3188 return RValue<Byte16>(value); 3189 } 3190 3191 RValue<Byte16> Byte16::operator=(const Reference<Byte16> &rhs) 3192 { 3193 Value *value = rhs.loadValue(); 3194 storeValue(value); 3195 3196 return RValue<Byte16>(value); 3197 } 3198 3199 Type *Byte16::getType() 3200 { 3201 return T(Ice::IceType_v16i8); 3202 } 3203 3204 Type *SByte16::getType() 3205 { 3206 return T(Ice::IceType_v16i8); 3207 } 3208 3209 Short2::Short2(RValue<Short4> cast) 3210 { 3211 storeValue(Nucleus::createBitCast(cast.value, getType())); 3212 } 3213 3214 Type *Short2::getType() 3215 { 3216 return T(Type_v2i16); 3217 } 3218 3219 UShort2::UShort2(RValue<UShort4> cast) 3220 { 3221 storeValue(Nucleus::createBitCast(cast.value, getType())); 3222 } 3223 3224 Type *UShort2::getType() 3225 { 3226 return T(Type_v2i16); 3227 } 3228 3229 Short4::Short4(RValue<Int> cast) 3230 { 3231 Value *vector = loadValue(); 3232 Value *element = Nucleus::createTrunc(cast.value, Short::getType()); 3233 Value *insert = Nucleus::createInsertElement(vector, element, 0); 3234 Value *swizzle = Swizzle(RValue<Short4>(insert), 0x00).value; 3235 3236 storeValue(swizzle); 3237 } 3238 3239 Short4::Short4(RValue<Int4> cast) 3240 { 3241 int select[8] = {0, 2, 4, 6, 0, 2, 4, 6}; 3242 Value *short8 = Nucleus::createBitCast(cast.value, Short8::getType()); 3243 Value *packed = Nucleus::createShuffleVector(short8, short8, select); 3244 3245 Value *int2 = RValue<Int2>(Int2(As<Int4>(packed))).value; 3246 Value *short4 = Nucleus::createBitCast(int2, Short4::getType()); 3247 3248 storeValue(short4); 3249 } 3250 3251 // Short4::Short4(RValue<Float> cast) 3252 // { 3253 // } 3254 3255 Short4::Short4(RValue<Float4> cast) 3256 { 3257 assert(false && "UNIMPLEMENTED"); 3258 } 3259 3260 Short4::Short4(short xyzw) 3261 { 3262 int64_t constantVector[4] = {xyzw, xyzw, xyzw, xyzw}; 3263 storeValue(Nucleus::createConstantVector(constantVector, getType())); 3264 } 3265 3266 Short4::Short4(short x, short y, short z, short w) 3267 { 3268 int64_t constantVector[4] = {x, y, z, w}; 3269 storeValue(Nucleus::createConstantVector(constantVector, getType())); 3270 } 3271 3272 Short4::Short4(RValue<Short4> rhs) 3273 { 3274 storeValue(rhs.value); 3275 } 3276 3277 Short4::Short4(const Short4 &rhs) 3278 { 3279 Value *value = rhs.loadValue(); 3280 storeValue(value); 3281 } 3282 3283 Short4::Short4(const Reference<Short4> &rhs) 3284 { 3285 Value *value = rhs.loadValue(); 3286 storeValue(value); 3287 } 3288 3289 Short4::Short4(RValue<UShort4> rhs) 3290 { 3291 storeValue(rhs.value); 3292 } 3293 3294 Short4::Short4(const UShort4 &rhs) 3295 { 3296 storeValue(rhs.loadValue()); 3297 } 3298 3299 Short4::Short4(const Reference<UShort4> &rhs) 3300 { 3301 storeValue(rhs.loadValue()); 3302 } 3303 3304 RValue<Short4> Short4::operator=(RValue<Short4> rhs) 3305 { 3306 storeValue(rhs.value); 3307 3308 return rhs; 3309 } 3310 3311 RValue<Short4> Short4::operator=(const Short4 &rhs) 3312 { 3313 Value *value = rhs.loadValue(); 3314 storeValue(value); 3315 3316 return RValue<Short4>(value); 3317 } 3318 3319 RValue<Short4> Short4::operator=(const Reference<Short4> &rhs) 3320 { 3321 Value *value = rhs.loadValue(); 3322 storeValue(value); 3323 3324 return RValue<Short4>(value); 3325 } 3326 3327 RValue<Short4> Short4::operator=(RValue<UShort4> rhs) 3328 { 3329 storeValue(rhs.value); 3330 3331 return RValue<Short4>(rhs); 3332 } 3333 3334 RValue<Short4> Short4::operator=(const UShort4 &rhs) 3335 { 3336 Value *value = rhs.loadValue(); 3337 storeValue(value); 3338 3339 return RValue<Short4>(value); 3340 } 3341 3342 RValue<Short4> Short4::operator=(const Reference<UShort4> &rhs) 3343 { 3344 Value *value = rhs.loadValue(); 3345 storeValue(value); 3346 3347 return RValue<Short4>(value); 3348 } 3349 3350 RValue<Short4> operator+(RValue<Short4> lhs, RValue<Short4> rhs) 3351 { 3352 return RValue<Short4>(Nucleus::createAdd(lhs.value, rhs.value)); 3353 } 3354 3355 RValue<Short4> operator-(RValue<Short4> lhs, RValue<Short4> rhs) 3356 { 3357 return RValue<Short4>(Nucleus::createSub(lhs.value, rhs.value)); 3358 } 3359 3360 RValue<Short4> operator*(RValue<Short4> lhs, RValue<Short4> rhs) 3361 { 3362 return RValue<Short4>(Nucleus::createMul(lhs.value, rhs.value)); 3363 } 3364 3365 // RValue<Short4> operator/(RValue<Short4> lhs, RValue<Short4> rhs) 3366 // { 3367 // return RValue<Short4>(Nucleus::createSDiv(lhs.value, rhs.value)); 3368 // } 3369 3370 // RValue<Short4> operator%(RValue<Short4> lhs, RValue<Short4> rhs) 3371 // { 3372 // return RValue<Short4>(Nucleus::createSRem(lhs.value, rhs.value)); 3373 // } 3374 3375 RValue<Short4> operator&(RValue<Short4> lhs, RValue<Short4> rhs) 3376 { 3377 return RValue<Short4>(Nucleus::createAnd(lhs.value, rhs.value)); 3378 } 3379 3380 RValue<Short4> operator|(RValue<Short4> lhs, RValue<Short4> rhs) 3381 { 3382 return RValue<Short4>(Nucleus::createOr(lhs.value, rhs.value)); 3383 } 3384 3385 RValue<Short4> operator^(RValue<Short4> lhs, RValue<Short4> rhs) 3386 { 3387 return RValue<Short4>(Nucleus::createXor(lhs.value, rhs.value)); 3388 } 3389 3390 RValue<Short4> operator<<(RValue<Short4> lhs, unsigned char rhs) 3391 { 3392 if(emulateIntrinsics) 3393 { 3394 Short4 result; 3395 result = Insert(result, Extract(lhs, 0) << Short(rhs), 0); 3396 result = Insert(result, Extract(lhs, 1) << Short(rhs), 1); 3397 result = Insert(result, Extract(lhs, 2) << Short(rhs), 2); 3398 result = Insert(result, Extract(lhs, 3) << Short(rhs), 3); 3399 3400 return result; 3401 } 3402 else 3403 { 3404 return RValue<Short4>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 3405 } 3406 } 3407 3408 RValue<Short4> operator>>(RValue<Short4> lhs, unsigned char rhs) 3409 { 3410 if(emulateIntrinsics) 3411 { 3412 Short4 result; 3413 result = Insert(result, Extract(lhs, 0) >> Short(rhs), 0); 3414 result = Insert(result, Extract(lhs, 1) >> Short(rhs), 1); 3415 result = Insert(result, Extract(lhs, 2) >> Short(rhs), 2); 3416 result = Insert(result, Extract(lhs, 3) >> Short(rhs), 3); 3417 3418 return result; 3419 } 3420 else 3421 { 3422 return RValue<Short4>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 3423 } 3424 } 3425 3426 RValue<Short4> operator+=(Short4 &lhs, RValue<Short4> rhs) 3427 { 3428 return lhs = lhs + rhs; 3429 } 3430 3431 RValue<Short4> operator-=(Short4 &lhs, RValue<Short4> rhs) 3432 { 3433 return lhs = lhs - rhs; 3434 } 3435 3436 RValue<Short4> operator*=(Short4 &lhs, RValue<Short4> rhs) 3437 { 3438 return lhs = lhs * rhs; 3439 } 3440 3441 // RValue<Short4> operator/=(Short4 &lhs, RValue<Short4> rhs) 3442 // { 3443 // return lhs = lhs / rhs; 3444 // } 3445 3446 // RValue<Short4> operator%=(Short4 &lhs, RValue<Short4> rhs) 3447 // { 3448 // return lhs = lhs % rhs; 3449 // } 3450 3451 RValue<Short4> operator&=(Short4 &lhs, RValue<Short4> rhs) 3452 { 3453 return lhs = lhs & rhs; 3454 } 3455 3456 RValue<Short4> operator|=(Short4 &lhs, RValue<Short4> rhs) 3457 { 3458 return lhs = lhs | rhs; 3459 } 3460 3461 RValue<Short4> operator^=(Short4 &lhs, RValue<Short4> rhs) 3462 { 3463 return lhs = lhs ^ rhs; 3464 } 3465 3466 RValue<Short4> operator<<=(Short4 &lhs, unsigned char rhs) 3467 { 3468 return lhs = lhs << rhs; 3469 } 3470 3471 RValue<Short4> operator>>=(Short4 &lhs, unsigned char rhs) 3472 { 3473 return lhs = lhs >> rhs; 3474 } 3475 3476 // RValue<Short4> operator+(RValue<Short4> val) 3477 // { 3478 // return val; 3479 // } 3480 3481 RValue<Short4> operator-(RValue<Short4> val) 3482 { 3483 return RValue<Short4>(Nucleus::createNeg(val.value)); 3484 } 3485 3486 RValue<Short4> operator~(RValue<Short4> val) 3487 { 3488 return RValue<Short4>(Nucleus::createNot(val.value)); 3489 } 3490 3491 RValue<Short4> RoundShort4(RValue<Float4> cast) 3492 { 3493 RValue<Int4> int4 = RoundInt(cast); 3494 return As<Short4>(PackSigned(int4, int4)); 3495 } 3496 3497 RValue<Short4> Max(RValue<Short4> x, RValue<Short4> y) 3498 { 3499 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1); 3500 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value, y.value); 3501 ::basicBlock->appendInst(cmp); 3502 3503 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3504 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 3505 ::basicBlock->appendInst(select); 3506 3507 return RValue<Short4>(V(result)); 3508 } 3509 3510 RValue<Short4> Min(RValue<Short4> x, RValue<Short4> y) 3511 { 3512 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1); 3513 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value, y.value); 3514 ::basicBlock->appendInst(cmp); 3515 3516 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3517 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 3518 ::basicBlock->appendInst(select); 3519 3520 return RValue<Short4>(V(result)); 3521 } 3522 3523 RValue<Short> SaturateSigned(RValue<Int> x) 3524 { 3525 return Short(IfThenElse(x > 0x7FFF, Int(0x7FFF), IfThenElse(x < -0x8000, Int(0x8000), x))); 3526 } 3527 3528 RValue<Short4> AddSat(RValue<Short4> x, RValue<Short4> y) 3529 { 3530 if(emulateIntrinsics) 3531 { 3532 Short4 result; 3533 result = Insert(result, SaturateSigned(Int(Extract(x, 0)) + Int(Extract(y, 0))), 0); 3534 result = Insert(result, SaturateSigned(Int(Extract(x, 1)) + Int(Extract(y, 1))), 1); 3535 result = Insert(result, SaturateSigned(Int(Extract(x, 2)) + Int(Extract(y, 2))), 2); 3536 result = Insert(result, SaturateSigned(Int(Extract(x, 3)) + Int(Extract(y, 3))), 3); 3537 3538 return result; 3539 } 3540 else 3541 { 3542 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3543 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::AddSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3544 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3545 auto paddsw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3546 paddsw->addArg(x.value); 3547 paddsw->addArg(y.value); 3548 ::basicBlock->appendInst(paddsw); 3549 3550 return RValue<Short4>(V(result)); 3551 } 3552 } 3553 3554 RValue<Short4> SubSat(RValue<Short4> x, RValue<Short4> y) 3555 { 3556 if(emulateIntrinsics) 3557 { 3558 Short4 result; 3559 result = Insert(result, SaturateSigned(Int(Extract(x, 0)) - Int(Extract(y, 0))), 0); 3560 result = Insert(result, SaturateSigned(Int(Extract(x, 1)) - Int(Extract(y, 1))), 1); 3561 result = Insert(result, SaturateSigned(Int(Extract(x, 2)) - Int(Extract(y, 2))), 2); 3562 result = Insert(result, SaturateSigned(Int(Extract(x, 3)) - Int(Extract(y, 3))), 3); 3563 3564 return result; 3565 } 3566 else 3567 { 3568 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3569 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SubtractSaturateSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3570 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3571 auto psubsw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3572 psubsw->addArg(x.value); 3573 psubsw->addArg(y.value); 3574 ::basicBlock->appendInst(psubsw); 3575 3576 return RValue<Short4>(V(result)); 3577 } 3578 } 3579 3580 RValue<Short4> MulHigh(RValue<Short4> x, RValue<Short4> y) 3581 { 3582 if(emulateIntrinsics) 3583 { 3584 Short4 result; 3585 result = Insert(result, Short((Int(Extract(x, 0)) * Int(Extract(y, 0))) >> 16), 0); 3586 result = Insert(result, Short((Int(Extract(x, 1)) * Int(Extract(y, 1))) >> 16), 1); 3587 result = Insert(result, Short((Int(Extract(x, 2)) * Int(Extract(y, 2))) >> 16), 2); 3588 result = Insert(result, Short((Int(Extract(x, 3)) * Int(Extract(y, 3))) >> 16), 3); 3589 3590 return result; 3591 } 3592 else 3593 { 3594 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3595 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::MultiplyHighSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3596 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3597 auto pmulhw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3598 pmulhw->addArg(x.value); 3599 pmulhw->addArg(y.value); 3600 ::basicBlock->appendInst(pmulhw); 3601 3602 return RValue<Short4>(V(result)); 3603 } 3604 } 3605 3606 RValue<Int2> MulAdd(RValue<Short4> x, RValue<Short4> y) 3607 { 3608 if(emulateIntrinsics) 3609 { 3610 Int2 result; 3611 result = Insert(result, Int(Extract(x, 0)) * Int(Extract(y, 0)) + Int(Extract(x, 1)) * Int(Extract(y, 1)), 0); 3612 result = Insert(result, Int(Extract(x, 2)) * Int(Extract(y, 2)) + Int(Extract(x, 3)) * Int(Extract(y, 3)), 1); 3613 3614 return result; 3615 } 3616 else 3617 { 3618 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3619 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::MultiplyAddPairs, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3620 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3621 auto pmaddwd = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3622 pmaddwd->addArg(x.value); 3623 pmaddwd->addArg(y.value); 3624 ::basicBlock->appendInst(pmaddwd); 3625 3626 return As<Int2>(V(result)); 3627 } 3628 } 3629 3630 RValue<SByte8> PackSigned(RValue<Short4> x, RValue<Short4> y) 3631 { 3632 if(emulateIntrinsics) 3633 { 3634 SByte8 result; 3635 result = Insert(result, SaturateSigned(Extract(x, 0)), 0); 3636 result = Insert(result, SaturateSigned(Extract(x, 1)), 1); 3637 result = Insert(result, SaturateSigned(Extract(x, 2)), 2); 3638 result = Insert(result, SaturateSigned(Extract(x, 3)), 3); 3639 result = Insert(result, SaturateSigned(Extract(y, 0)), 4); 3640 result = Insert(result, SaturateSigned(Extract(y, 1)), 5); 3641 result = Insert(result, SaturateSigned(Extract(y, 2)), 6); 3642 result = Insert(result, SaturateSigned(Extract(y, 3)), 7); 3643 3644 return result; 3645 } 3646 else 3647 { 3648 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 3649 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3650 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3651 auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3652 pack->addArg(x.value); 3653 pack->addArg(y.value); 3654 ::basicBlock->appendInst(pack); 3655 3656 return As<SByte8>(Swizzle(As<Int4>(V(result)), 0x88)); 3657 } 3658 } 3659 3660 RValue<Byte8> PackUnsigned(RValue<Short4> x, RValue<Short4> y) 3661 { 3662 if(emulateIntrinsics) 3663 { 3664 Byte8 result; 3665 result = Insert(result, SaturateUnsigned(Extract(x, 0)), 0); 3666 result = Insert(result, SaturateUnsigned(Extract(x, 1)), 1); 3667 result = Insert(result, SaturateUnsigned(Extract(x, 2)), 2); 3668 result = Insert(result, SaturateUnsigned(Extract(x, 3)), 3); 3669 result = Insert(result, SaturateUnsigned(Extract(y, 0)), 4); 3670 result = Insert(result, SaturateUnsigned(Extract(y, 1)), 5); 3671 result = Insert(result, SaturateUnsigned(Extract(y, 2)), 6); 3672 result = Insert(result, SaturateUnsigned(Extract(y, 3)), 7); 3673 3674 return result; 3675 } 3676 else 3677 { 3678 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v16i8); 3679 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 3680 auto target = ::context->getConstantUndef(Ice::IceType_i32); 3681 auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 3682 pack->addArg(x.value); 3683 pack->addArg(y.value); 3684 ::basicBlock->appendInst(pack); 3685 3686 return As<Byte8>(Swizzle(As<Int4>(V(result)), 0x88)); 3687 } 3688 } 3689 3690 RValue<Int2> UnpackLow(RValue<Short4> x, RValue<Short4> y) 3691 { 3692 int shuffle[8] = {0, 8, 1, 9, 2, 10, 3, 11}; // Real type is v8i16 3693 return As<Int2>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 3694 } 3695 3696 RValue<Int2> UnpackHigh(RValue<Short4> x, RValue<Short4> y) 3697 { 3698 int shuffle[8] = {0, 8, 1, 9, 2, 10, 3, 11}; // Real type is v8i16 3699 auto lowHigh = RValue<Short8>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 3700 return As<Int2>(Swizzle(As<Int4>(lowHigh), 0xEE)); 3701 } 3702 3703 RValue<Short4> Swizzle(RValue<Short4> x, unsigned char select) 3704 { 3705 // Real type is v8i16 3706 int shuffle[8] = 3707 { 3708 (select >> 0) & 0x03, 3709 (select >> 2) & 0x03, 3710 (select >> 4) & 0x03, 3711 (select >> 6) & 0x03, 3712 (select >> 0) & 0x03, 3713 (select >> 2) & 0x03, 3714 (select >> 4) & 0x03, 3715 (select >> 6) & 0x03, 3716 }; 3717 3718 return RValue<Short4>(Nucleus::createShuffleVector(x.value, x.value, shuffle)); 3719 } 3720 3721 RValue<Short4> Insert(RValue<Short4> val, RValue<Short> element, int i) 3722 { 3723 return RValue<Short4>(Nucleus::createInsertElement(val.value, element.value, i)); 3724 } 3725 3726 RValue<Short> Extract(RValue<Short4> val, int i) 3727 { 3728 return RValue<Short>(Nucleus::createExtractElement(val.value, Short::getType(), i)); 3729 } 3730 3731 RValue<Short4> CmpGT(RValue<Short4> x, RValue<Short4> y) 3732 { 3733 return RValue<Short4>(createIntCompare(Ice::InstIcmp::Sgt, x.value, y.value)); 3734 } 3735 3736 RValue<Short4> CmpEQ(RValue<Short4> x, RValue<Short4> y) 3737 { 3738 return RValue<Short4>(Nucleus::createICmpEQ(x.value, y.value)); 3739 } 3740 3741 Type *Short4::getType() 3742 { 3743 return T(Type_v4i16); 3744 } 3745 3746 UShort4::UShort4(RValue<Int4> cast) 3747 { 3748 *this = Short4(cast); 3749 } 3750 3751 UShort4::UShort4(RValue<Float4> cast, bool saturate) 3752 { 3753 if(saturate) 3754 { 3755 if(CPUID::SSE4_1) 3756 { 3757 // x86 produces 0x80000000 on 32-bit integer overflow/underflow. 3758 // PackUnsigned takes care of 0x0000 saturation. 3759 Int4 int4(Min(cast, Float4(0xFFFF))); 3760 *this = As<UShort4>(PackUnsigned(int4, int4)); 3761 } 3762 else if(CPUID::ARM) 3763 { 3764 // ARM saturates the 32-bit integer result on overflow/undeflow. 3765 Int4 int4(cast); 3766 *this = As<UShort4>(PackUnsigned(int4, int4)); 3767 } 3768 else 3769 { 3770 *this = Short4(Int4(Max(Min(cast, Float4(0xFFFF)), Float4(0x0000)))); 3771 } 3772 } 3773 else 3774 { 3775 *this = Short4(Int4(cast)); 3776 } 3777 } 3778 3779 UShort4::UShort4(unsigned short xyzw) 3780 { 3781 int64_t constantVector[4] = {xyzw, xyzw, xyzw, xyzw}; 3782 storeValue(Nucleus::createConstantVector(constantVector, getType())); 3783 } 3784 3785 UShort4::UShort4(unsigned short x, unsigned short y, unsigned short z, unsigned short w) 3786 { 3787 int64_t constantVector[4] = {x, y, z, w}; 3788 storeValue(Nucleus::createConstantVector(constantVector, getType())); 3789 } 3790 3791 UShort4::UShort4(RValue<UShort4> rhs) 3792 { 3793 storeValue(rhs.value); 3794 } 3795 3796 UShort4::UShort4(const UShort4 &rhs) 3797 { 3798 Value *value = rhs.loadValue(); 3799 storeValue(value); 3800 } 3801 3802 UShort4::UShort4(const Reference<UShort4> &rhs) 3803 { 3804 Value *value = rhs.loadValue(); 3805 storeValue(value); 3806 } 3807 3808 UShort4::UShort4(RValue<Short4> rhs) 3809 { 3810 storeValue(rhs.value); 3811 } 3812 3813 UShort4::UShort4(const Short4 &rhs) 3814 { 3815 Value *value = rhs.loadValue(); 3816 storeValue(value); 3817 } 3818 3819 UShort4::UShort4(const Reference<Short4> &rhs) 3820 { 3821 Value *value = rhs.loadValue(); 3822 storeValue(value); 3823 } 3824 3825 RValue<UShort4> UShort4::operator=(RValue<UShort4> rhs) 3826 { 3827 storeValue(rhs.value); 3828 3829 return rhs; 3830 } 3831 3832 RValue<UShort4> UShort4::operator=(const UShort4 &rhs) 3833 { 3834 Value *value = rhs.loadValue(); 3835 storeValue(value); 3836 3837 return RValue<UShort4>(value); 3838 } 3839 3840 RValue<UShort4> UShort4::operator=(const Reference<UShort4> &rhs) 3841 { 3842 Value *value = rhs.loadValue(); 3843 storeValue(value); 3844 3845 return RValue<UShort4>(value); 3846 } 3847 3848 RValue<UShort4> UShort4::operator=(RValue<Short4> rhs) 3849 { 3850 storeValue(rhs.value); 3851 3852 return RValue<UShort4>(rhs); 3853 } 3854 3855 RValue<UShort4> UShort4::operator=(const Short4 &rhs) 3856 { 3857 Value *value = rhs.loadValue(); 3858 storeValue(value); 3859 3860 return RValue<UShort4>(value); 3861 } 3862 3863 RValue<UShort4> UShort4::operator=(const Reference<Short4> &rhs) 3864 { 3865 Value *value = rhs.loadValue(); 3866 storeValue(value); 3867 3868 return RValue<UShort4>(value); 3869 } 3870 3871 RValue<UShort4> operator+(RValue<UShort4> lhs, RValue<UShort4> rhs) 3872 { 3873 return RValue<UShort4>(Nucleus::createAdd(lhs.value, rhs.value)); 3874 } 3875 3876 RValue<UShort4> operator-(RValue<UShort4> lhs, RValue<UShort4> rhs) 3877 { 3878 return RValue<UShort4>(Nucleus::createSub(lhs.value, rhs.value)); 3879 } 3880 3881 RValue<UShort4> operator*(RValue<UShort4> lhs, RValue<UShort4> rhs) 3882 { 3883 return RValue<UShort4>(Nucleus::createMul(lhs.value, rhs.value)); 3884 } 3885 3886 RValue<UShort4> operator&(RValue<UShort4> lhs, RValue<UShort4> rhs) 3887 { 3888 return RValue<UShort4>(Nucleus::createAnd(lhs.value, rhs.value)); 3889 } 3890 3891 RValue<UShort4> operator|(RValue<UShort4> lhs, RValue<UShort4> rhs) 3892 { 3893 return RValue<UShort4>(Nucleus::createOr(lhs.value, rhs.value)); 3894 } 3895 3896 RValue<UShort4> operator^(RValue<UShort4> lhs, RValue<UShort4> rhs) 3897 { 3898 return RValue<UShort4>(Nucleus::createXor(lhs.value, rhs.value)); 3899 } 3900 3901 RValue<UShort> Extract(RValue<UShort4> val, int i) 3902 { 3903 return RValue<UShort>(Nucleus::createExtractElement(val.value, UShort::getType(), i)); 3904 } 3905 3906 RValue<UShort4> Insert(RValue<UShort4> val, RValue<UShort> element, int i) 3907 { 3908 return RValue<UShort4>(Nucleus::createInsertElement(val.value, element.value, i)); 3909 } 3910 3911 RValue<UShort4> operator<<(RValue<UShort4> lhs, unsigned char rhs) 3912 { 3913 if(emulateIntrinsics) 3914 { 3915 UShort4 result; 3916 result = Insert(result, Extract(lhs, 0) << UShort(rhs), 0); 3917 result = Insert(result, Extract(lhs, 1) << UShort(rhs), 1); 3918 result = Insert(result, Extract(lhs, 2) << UShort(rhs), 2); 3919 result = Insert(result, Extract(lhs, 3) << UShort(rhs), 3); 3920 3921 return result; 3922 } 3923 else 3924 { 3925 return RValue<UShort4>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 3926 } 3927 } 3928 3929 RValue<UShort4> operator>>(RValue<UShort4> lhs, unsigned char rhs) 3930 { 3931 if(emulateIntrinsics) 3932 { 3933 UShort4 result; 3934 result = Insert(result, Extract(lhs, 0) >> UShort(rhs), 0); 3935 result = Insert(result, Extract(lhs, 1) >> UShort(rhs), 1); 3936 result = Insert(result, Extract(lhs, 2) >> UShort(rhs), 2); 3937 result = Insert(result, Extract(lhs, 3) >> UShort(rhs), 3); 3938 3939 return result; 3940 } 3941 else 3942 { 3943 return RValue<UShort4>(Nucleus::createLShr(lhs.value, V(::context->getConstantInt32(rhs)))); 3944 } 3945 } 3946 3947 RValue<UShort4> operator<<=(UShort4 &lhs, unsigned char rhs) 3948 { 3949 return lhs = lhs << rhs; 3950 } 3951 3952 RValue<UShort4> operator>>=(UShort4 &lhs, unsigned char rhs) 3953 { 3954 return lhs = lhs >> rhs; 3955 } 3956 3957 RValue<UShort4> operator~(RValue<UShort4> val) 3958 { 3959 return RValue<UShort4>(Nucleus::createNot(val.value)); 3960 } 3961 3962 RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y) 3963 { 3964 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1); 3965 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value, y.value); 3966 ::basicBlock->appendInst(cmp); 3967 3968 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3969 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 3970 ::basicBlock->appendInst(select); 3971 3972 return RValue<UShort4>(V(result)); 3973 } 3974 3975 RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y) 3976 { 3977 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1); 3978 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value, y.value); 3979 ::basicBlock->appendInst(cmp); 3980 3981 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 3982 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 3983 ::basicBlock->appendInst(select); 3984 3985 return RValue<UShort4>(V(result)); 3986 } 3987 3988 RValue<UShort> SaturateUnsigned(RValue<Int> x) 3989 { 3990 return UShort(IfThenElse(x > 0xFFFF, Int(0xFFFF), IfThenElse(x < 0, Int(0), x))); 3991 } 3992 3993 RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y) 3994 { 3995 if(emulateIntrinsics) 3996 { 3997 UShort4 result; 3998 result = Insert(result, SaturateUnsigned(Int(Extract(x, 0)) + Int(Extract(y, 0))), 0); 3999 result = Insert(result, SaturateUnsigned(Int(Extract(x, 1)) + Int(Extract(y, 1))), 1); 4000 result = Insert(result, SaturateUnsigned(Int(Extract(x, 2)) + Int(Extract(y, 2))), 2); 4001 result = Insert(result, SaturateUnsigned(Int(Extract(x, 3)) + Int(Extract(y, 3))), 3); 4002 4003 return result; 4004 } 4005 else 4006 { 4007 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 4008 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::AddSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 4009 auto target = ::context->getConstantUndef(Ice::IceType_i32); 4010 auto paddusw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 4011 paddusw->addArg(x.value); 4012 paddusw->addArg(y.value); 4013 ::basicBlock->appendInst(paddusw); 4014 4015 return RValue<UShort4>(V(result)); 4016 } 4017 } 4018 4019 RValue<UShort4> SubSat(RValue<UShort4> x, RValue<UShort4> y) 4020 { 4021 if(emulateIntrinsics) 4022 { 4023 UShort4 result; 4024 result = Insert(result, SaturateUnsigned(Int(Extract(x, 0)) - Int(Extract(y, 0))), 0); 4025 result = Insert(result, SaturateUnsigned(Int(Extract(x, 1)) - Int(Extract(y, 1))), 1); 4026 result = Insert(result, SaturateUnsigned(Int(Extract(x, 2)) - Int(Extract(y, 2))), 2); 4027 result = Insert(result, SaturateUnsigned(Int(Extract(x, 3)) - Int(Extract(y, 3))), 3); 4028 4029 return result; 4030 } 4031 else 4032 { 4033 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 4034 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SubtractSaturateUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 4035 auto target = ::context->getConstantUndef(Ice::IceType_i32); 4036 auto psubusw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 4037 psubusw->addArg(x.value); 4038 psubusw->addArg(y.value); 4039 ::basicBlock->appendInst(psubusw); 4040 4041 return RValue<UShort4>(V(result)); 4042 } 4043 } 4044 4045 RValue<UShort4> MulHigh(RValue<UShort4> x, RValue<UShort4> y) 4046 { 4047 if(emulateIntrinsics) 4048 { 4049 UShort4 result; 4050 result = Insert(result, UShort((UInt(Extract(x, 0)) * UInt(Extract(y, 0))) >> 16), 0); 4051 result = Insert(result, UShort((UInt(Extract(x, 1)) * UInt(Extract(y, 1))) >> 16), 1); 4052 result = Insert(result, UShort((UInt(Extract(x, 2)) * UInt(Extract(y, 2))) >> 16), 2); 4053 result = Insert(result, UShort((UInt(Extract(x, 3)) * UInt(Extract(y, 3))) >> 16), 3); 4054 4055 return result; 4056 } 4057 else 4058 { 4059 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 4060 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::MultiplyHighUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 4061 auto target = ::context->getConstantUndef(Ice::IceType_i32); 4062 auto pmulhuw = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 4063 pmulhuw->addArg(x.value); 4064 pmulhuw->addArg(y.value); 4065 ::basicBlock->appendInst(pmulhuw); 4066 4067 return RValue<UShort4>(V(result)); 4068 } 4069 } 4070 4071 RValue<UShort4> Average(RValue<UShort4> x, RValue<UShort4> y) 4072 { 4073 assert(false && "UNIMPLEMENTED"); return RValue<UShort4>(V(nullptr)); 4074 } 4075 4076 Type *UShort4::getType() 4077 { 4078 return T(Type_v4i16); 4079 } 4080 4081 Short8::Short8(short c) 4082 { 4083 int64_t constantVector[8] = {c, c, c, c, c, c, c, c}; 4084 storeValue(Nucleus::createConstantVector(constantVector, getType())); 4085 } 4086 4087 Short8::Short8(short c0, short c1, short c2, short c3, short c4, short c5, short c6, short c7) 4088 { 4089 int64_t constantVector[8] = {c0, c1, c2, c3, c4, c5, c6, c7}; 4090 storeValue(Nucleus::createConstantVector(constantVector, getType())); 4091 } 4092 4093 Short8::Short8(RValue<Short8> rhs) 4094 { 4095 storeValue(rhs.value); 4096 } 4097 4098 Short8::Short8(const Reference<Short8> &rhs) 4099 { 4100 Value *value = rhs.loadValue(); 4101 storeValue(value); 4102 } 4103 4104 Short8::Short8(RValue<Short4> lo, RValue<Short4> hi) 4105 { 4106 int shuffle[8] = {0, 1, 2, 3, 8, 9, 10, 11}; // Real type is v8i16 4107 Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle); 4108 4109 storeValue(packed); 4110 } 4111 4112 RValue<Short8> operator+(RValue<Short8> lhs, RValue<Short8> rhs) 4113 { 4114 return RValue<Short8>(Nucleus::createAdd(lhs.value, rhs.value)); 4115 } 4116 4117 RValue<Short8> operator&(RValue<Short8> lhs, RValue<Short8> rhs) 4118 { 4119 return RValue<Short8>(Nucleus::createAnd(lhs.value, rhs.value)); 4120 } 4121 4122 RValue<Short> Extract(RValue<Short8> val, int i) 4123 { 4124 return RValue<Short>(Nucleus::createExtractElement(val.value, Short::getType(), i)); 4125 } 4126 4127 RValue<Short8> Insert(RValue<Short8> val, RValue<Short> element, int i) 4128 { 4129 return RValue<Short8>(Nucleus::createInsertElement(val.value, element.value, i)); 4130 } 4131 4132 RValue<Short8> operator<<(RValue<Short8> lhs, unsigned char rhs) 4133 { 4134 if(emulateIntrinsics) 4135 { 4136 Short8 result; 4137 result = Insert(result, Extract(lhs, 0) << Short(rhs), 0); 4138 result = Insert(result, Extract(lhs, 1) << Short(rhs), 1); 4139 result = Insert(result, Extract(lhs, 2) << Short(rhs), 2); 4140 result = Insert(result, Extract(lhs, 3) << Short(rhs), 3); 4141 result = Insert(result, Extract(lhs, 4) << Short(rhs), 4); 4142 result = Insert(result, Extract(lhs, 5) << Short(rhs), 5); 4143 result = Insert(result, Extract(lhs, 6) << Short(rhs), 6); 4144 result = Insert(result, Extract(lhs, 7) << Short(rhs), 7); 4145 4146 return result; 4147 } 4148 else 4149 { 4150 return RValue<Short8>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 4151 } 4152 } 4153 4154 RValue<Short8> operator>>(RValue<Short8> lhs, unsigned char rhs) 4155 { 4156 if(emulateIntrinsics) 4157 { 4158 Short8 result; 4159 result = Insert(result, Extract(lhs, 0) >> Short(rhs), 0); 4160 result = Insert(result, Extract(lhs, 1) >> Short(rhs), 1); 4161 result = Insert(result, Extract(lhs, 2) >> Short(rhs), 2); 4162 result = Insert(result, Extract(lhs, 3) >> Short(rhs), 3); 4163 result = Insert(result, Extract(lhs, 4) >> Short(rhs), 4); 4164 result = Insert(result, Extract(lhs, 5) >> Short(rhs), 5); 4165 result = Insert(result, Extract(lhs, 6) >> Short(rhs), 6); 4166 result = Insert(result, Extract(lhs, 7) >> Short(rhs), 7); 4167 4168 return result; 4169 } 4170 else 4171 { 4172 return RValue<Short8>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 4173 } 4174 } 4175 4176 RValue<Int4> MulAdd(RValue<Short8> x, RValue<Short8> y) 4177 { 4178 assert(false && "UNIMPLEMENTED"); return RValue<Int4>(V(nullptr)); 4179 } 4180 4181 RValue<Int4> Abs(RValue<Int4> x) 4182 { 4183 auto negative = x >> 31; 4184 return (x ^ negative) - negative; 4185 } 4186 4187 RValue<Short8> MulHigh(RValue<Short8> x, RValue<Short8> y) 4188 { 4189 assert(false && "UNIMPLEMENTED"); return RValue<Short8>(V(nullptr)); 4190 } 4191 4192 Type *Short8::getType() 4193 { 4194 return T(Ice::IceType_v8i16); 4195 } 4196 4197 UShort8::UShort8(unsigned short c) 4198 { 4199 int64_t constantVector[8] = {c, c, c, c, c, c, c, c}; 4200 storeValue(Nucleus::createConstantVector(constantVector, getType())); 4201 } 4202 4203 UShort8::UShort8(unsigned short c0, unsigned short c1, unsigned short c2, unsigned short c3, unsigned short c4, unsigned short c5, unsigned short c6, unsigned short c7) 4204 { 4205 int64_t constantVector[8] = {c0, c1, c2, c3, c4, c5, c6, c7}; 4206 storeValue(Nucleus::createConstantVector(constantVector, getType())); 4207 } 4208 4209 UShort8::UShort8(RValue<UShort8> rhs) 4210 { 4211 storeValue(rhs.value); 4212 } 4213 4214 UShort8::UShort8(const Reference<UShort8> &rhs) 4215 { 4216 Value *value = rhs.loadValue(); 4217 storeValue(value); 4218 } 4219 4220 UShort8::UShort8(RValue<UShort4> lo, RValue<UShort4> hi) 4221 { 4222 int shuffle[8] = {0, 1, 2, 3, 8, 9, 10, 11}; // Real type is v8i16 4223 Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle); 4224 4225 storeValue(packed); 4226 } 4227 4228 RValue<UShort8> UShort8::operator=(RValue<UShort8> rhs) 4229 { 4230 storeValue(rhs.value); 4231 4232 return rhs; 4233 } 4234 4235 RValue<UShort8> UShort8::operator=(const UShort8 &rhs) 4236 { 4237 Value *value = rhs.loadValue(); 4238 storeValue(value); 4239 4240 return RValue<UShort8>(value); 4241 } 4242 4243 RValue<UShort8> UShort8::operator=(const Reference<UShort8> &rhs) 4244 { 4245 Value *value = rhs.loadValue(); 4246 storeValue(value); 4247 4248 return RValue<UShort8>(value); 4249 } 4250 4251 RValue<UShort8> operator&(RValue<UShort8> lhs, RValue<UShort8> rhs) 4252 { 4253 return RValue<UShort8>(Nucleus::createAnd(lhs.value, rhs.value)); 4254 } 4255 4256 RValue<UShort> Extract(RValue<UShort8> val, int i) 4257 { 4258 return RValue<UShort>(Nucleus::createExtractElement(val.value, UShort::getType(), i)); 4259 } 4260 4261 RValue<UShort8> Insert(RValue<UShort8> val, RValue<UShort> element, int i) 4262 { 4263 return RValue<UShort8>(Nucleus::createInsertElement(val.value, element.value, i)); 4264 } 4265 4266 RValue<UShort8> operator<<(RValue<UShort8> lhs, unsigned char rhs) 4267 { 4268 if(emulateIntrinsics) 4269 { 4270 UShort8 result; 4271 result = Insert(result, Extract(lhs, 0) << UShort(rhs), 0); 4272 result = Insert(result, Extract(lhs, 1) << UShort(rhs), 1); 4273 result = Insert(result, Extract(lhs, 2) << UShort(rhs), 2); 4274 result = Insert(result, Extract(lhs, 3) << UShort(rhs), 3); 4275 result = Insert(result, Extract(lhs, 4) << UShort(rhs), 4); 4276 result = Insert(result, Extract(lhs, 5) << UShort(rhs), 5); 4277 result = Insert(result, Extract(lhs, 6) << UShort(rhs), 6); 4278 result = Insert(result, Extract(lhs, 7) << UShort(rhs), 7); 4279 4280 return result; 4281 } 4282 else 4283 { 4284 return RValue<UShort8>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 4285 } 4286 } 4287 4288 RValue<UShort8> operator>>(RValue<UShort8> lhs, unsigned char rhs) 4289 { 4290 if(emulateIntrinsics) 4291 { 4292 UShort8 result; 4293 result = Insert(result, Extract(lhs, 0) >> UShort(rhs), 0); 4294 result = Insert(result, Extract(lhs, 1) >> UShort(rhs), 1); 4295 result = Insert(result, Extract(lhs, 2) >> UShort(rhs), 2); 4296 result = Insert(result, Extract(lhs, 3) >> UShort(rhs), 3); 4297 result = Insert(result, Extract(lhs, 4) >> UShort(rhs), 4); 4298 result = Insert(result, Extract(lhs, 5) >> UShort(rhs), 5); 4299 result = Insert(result, Extract(lhs, 6) >> UShort(rhs), 6); 4300 result = Insert(result, Extract(lhs, 7) >> UShort(rhs), 7); 4301 4302 return result; 4303 } 4304 else 4305 { 4306 return RValue<UShort8>(Nucleus::createLShr(lhs.value, V(::context->getConstantInt32(rhs)))); 4307 } 4308 } 4309 4310 RValue<UShort8> operator+(RValue<UShort8> lhs, RValue<UShort8> rhs) 4311 { 4312 return RValue<UShort8>(Nucleus::createAdd(lhs.value, rhs.value)); 4313 } 4314 4315 RValue<UShort8> operator*(RValue<UShort8> lhs, RValue<UShort8> rhs) 4316 { 4317 return RValue<UShort8>(Nucleus::createMul(lhs.value, rhs.value)); 4318 } 4319 4320 RValue<UShort8> operator+=(UShort8 &lhs, RValue<UShort8> rhs) 4321 { 4322 return lhs = lhs + rhs; 4323 } 4324 4325 RValue<UShort8> operator~(RValue<UShort8> val) 4326 { 4327 return RValue<UShort8>(Nucleus::createNot(val.value)); 4328 } 4329 4330 RValue<UShort8> Swizzle(RValue<UShort8> x, char select0, char select1, char select2, char select3, char select4, char select5, char select6, char select7) 4331 { 4332 assert(false && "UNIMPLEMENTED"); return RValue<UShort8>(V(nullptr)); 4333 } 4334 4335 RValue<UShort8> MulHigh(RValue<UShort8> x, RValue<UShort8> y) 4336 { 4337 assert(false && "UNIMPLEMENTED"); return RValue<UShort8>(V(nullptr)); 4338 } 4339 4340 // FIXME: Implement as Shuffle(x, y, Select(i0, ..., i16)) and Shuffle(x, y, SELECT_PACK_REPEAT(element)) 4341 // RValue<UShort8> PackRepeat(RValue<Byte16> x, RValue<Byte16> y, int element) 4342 // { 4343 // assert(false && "UNIMPLEMENTED"); return RValue<UShort8>(V(nullptr)); 4344 // } 4345 4346 Type *UShort8::getType() 4347 { 4348 return T(Ice::IceType_v8i16); 4349 } 4350 4351 Int::Int(Argument<Int> argument) 4352 { 4353 storeValue(argument.value); 4354 } 4355 4356 Int::Int(RValue<Byte> cast) 4357 { 4358 Value *integer = Nucleus::createZExt(cast.value, Int::getType()); 4359 4360 storeValue(integer); 4361 } 4362 4363 Int::Int(RValue<SByte> cast) 4364 { 4365 Value *integer = Nucleus::createSExt(cast.value, Int::getType()); 4366 4367 storeValue(integer); 4368 } 4369 4370 Int::Int(RValue<Short> cast) 4371 { 4372 Value *integer = Nucleus::createSExt(cast.value, Int::getType()); 4373 4374 storeValue(integer); 4375 } 4376 4377 Int::Int(RValue<UShort> cast) 4378 { 4379 Value *integer = Nucleus::createZExt(cast.value, Int::getType()); 4380 4381 storeValue(integer); 4382 } 4383 4384 Int::Int(RValue<Int2> cast) 4385 { 4386 *this = Extract(cast, 0); 4387 } 4388 4389 Int::Int(RValue<Long> cast) 4390 { 4391 Value *integer = Nucleus::createTrunc(cast.value, Int::getType()); 4392 4393 storeValue(integer); 4394 } 4395 4396 Int::Int(RValue<Float> cast) 4397 { 4398 Value *integer = Nucleus::createFPToSI(cast.value, Int::getType()); 4399 4400 storeValue(integer); 4401 } 4402 4403 Int::Int(int x) 4404 { 4405 storeValue(Nucleus::createConstantInt(x)); 4406 } 4407 4408 Int::Int(RValue<Int> rhs) 4409 { 4410 storeValue(rhs.value); 4411 } 4412 4413 Int::Int(RValue<UInt> rhs) 4414 { 4415 storeValue(rhs.value); 4416 } 4417 4418 Int::Int(const Int &rhs) 4419 { 4420 Value *value = rhs.loadValue(); 4421 storeValue(value); 4422 } 4423 4424 Int::Int(const Reference<Int> &rhs) 4425 { 4426 Value *value = rhs.loadValue(); 4427 storeValue(value); 4428 } 4429 4430 Int::Int(const UInt &rhs) 4431 { 4432 Value *value = rhs.loadValue(); 4433 storeValue(value); 4434 } 4435 4436 Int::Int(const Reference<UInt> &rhs) 4437 { 4438 Value *value = rhs.loadValue(); 4439 storeValue(value); 4440 } 4441 4442 RValue<Int> Int::operator=(int rhs) 4443 { 4444 return RValue<Int>(storeValue(Nucleus::createConstantInt(rhs))); 4445 } 4446 4447 RValue<Int> Int::operator=(RValue<Int> rhs) 4448 { 4449 storeValue(rhs.value); 4450 4451 return rhs; 4452 } 4453 4454 RValue<Int> Int::operator=(RValue<UInt> rhs) 4455 { 4456 storeValue(rhs.value); 4457 4458 return RValue<Int>(rhs); 4459 } 4460 4461 RValue<Int> Int::operator=(const Int &rhs) 4462 { 4463 Value *value = rhs.loadValue(); 4464 storeValue(value); 4465 4466 return RValue<Int>(value); 4467 } 4468 4469 RValue<Int> Int::operator=(const Reference<Int> &rhs) 4470 { 4471 Value *value = rhs.loadValue(); 4472 storeValue(value); 4473 4474 return RValue<Int>(value); 4475 } 4476 4477 RValue<Int> Int::operator=(const UInt &rhs) 4478 { 4479 Value *value = rhs.loadValue(); 4480 storeValue(value); 4481 4482 return RValue<Int>(value); 4483 } 4484 4485 RValue<Int> Int::operator=(const Reference<UInt> &rhs) 4486 { 4487 Value *value = rhs.loadValue(); 4488 storeValue(value); 4489 4490 return RValue<Int>(value); 4491 } 4492 4493 RValue<Int> operator+(RValue<Int> lhs, RValue<Int> rhs) 4494 { 4495 return RValue<Int>(Nucleus::createAdd(lhs.value, rhs.value)); 4496 } 4497 4498 RValue<Int> operator-(RValue<Int> lhs, RValue<Int> rhs) 4499 { 4500 return RValue<Int>(Nucleus::createSub(lhs.value, rhs.value)); 4501 } 4502 4503 RValue<Int> operator*(RValue<Int> lhs, RValue<Int> rhs) 4504 { 4505 return RValue<Int>(Nucleus::createMul(lhs.value, rhs.value)); 4506 } 4507 4508 RValue<Int> operator/(RValue<Int> lhs, RValue<Int> rhs) 4509 { 4510 return RValue<Int>(Nucleus::createSDiv(lhs.value, rhs.value)); 4511 } 4512 4513 RValue<Int> operator%(RValue<Int> lhs, RValue<Int> rhs) 4514 { 4515 return RValue<Int>(Nucleus::createSRem(lhs.value, rhs.value)); 4516 } 4517 4518 RValue<Int> operator&(RValue<Int> lhs, RValue<Int> rhs) 4519 { 4520 return RValue<Int>(Nucleus::createAnd(lhs.value, rhs.value)); 4521 } 4522 4523 RValue<Int> operator|(RValue<Int> lhs, RValue<Int> rhs) 4524 { 4525 return RValue<Int>(Nucleus::createOr(lhs.value, rhs.value)); 4526 } 4527 4528 RValue<Int> operator^(RValue<Int> lhs, RValue<Int> rhs) 4529 { 4530 return RValue<Int>(Nucleus::createXor(lhs.value, rhs.value)); 4531 } 4532 4533 RValue<Int> operator<<(RValue<Int> lhs, RValue<Int> rhs) 4534 { 4535 return RValue<Int>(Nucleus::createShl(lhs.value, rhs.value)); 4536 } 4537 4538 RValue<Int> operator>>(RValue<Int> lhs, RValue<Int> rhs) 4539 { 4540 return RValue<Int>(Nucleus::createAShr(lhs.value, rhs.value)); 4541 } 4542 4543 RValue<Int> operator+=(Int &lhs, RValue<Int> rhs) 4544 { 4545 return lhs = lhs + rhs; 4546 } 4547 4548 RValue<Int> operator-=(Int &lhs, RValue<Int> rhs) 4549 { 4550 return lhs = lhs - rhs; 4551 } 4552 4553 RValue<Int> operator*=(Int &lhs, RValue<Int> rhs) 4554 { 4555 return lhs = lhs * rhs; 4556 } 4557 4558 RValue<Int> operator/=(Int &lhs, RValue<Int> rhs) 4559 { 4560 return lhs = lhs / rhs; 4561 } 4562 4563 RValue<Int> operator%=(Int &lhs, RValue<Int> rhs) 4564 { 4565 return lhs = lhs % rhs; 4566 } 4567 4568 RValue<Int> operator&=(Int &lhs, RValue<Int> rhs) 4569 { 4570 return lhs = lhs & rhs; 4571 } 4572 4573 RValue<Int> operator|=(Int &lhs, RValue<Int> rhs) 4574 { 4575 return lhs = lhs | rhs; 4576 } 4577 4578 RValue<Int> operator^=(Int &lhs, RValue<Int> rhs) 4579 { 4580 return lhs = lhs ^ rhs; 4581 } 4582 4583 RValue<Int> operator<<=(Int &lhs, RValue<Int> rhs) 4584 { 4585 return lhs = lhs << rhs; 4586 } 4587 4588 RValue<Int> operator>>=(Int &lhs, RValue<Int> rhs) 4589 { 4590 return lhs = lhs >> rhs; 4591 } 4592 4593 RValue<Int> operator+(RValue<Int> val) 4594 { 4595 return val; 4596 } 4597 4598 RValue<Int> operator-(RValue<Int> val) 4599 { 4600 return RValue<Int>(Nucleus::createNeg(val.value)); 4601 } 4602 4603 RValue<Int> operator~(RValue<Int> val) 4604 { 4605 return RValue<Int>(Nucleus::createNot(val.value)); 4606 } 4607 4608 RValue<Int> operator++(Int &val, int) // Post-increment 4609 { 4610 RValue<Int> res = val; 4611 val += 1; 4612 return res; 4613 } 4614 4615 const Int &operator++(Int &val) // Pre-increment 4616 { 4617 val += 1; 4618 return val; 4619 } 4620 4621 RValue<Int> operator--(Int &val, int) // Post-decrement 4622 { 4623 RValue<Int> res = val; 4624 val -= 1; 4625 return res; 4626 } 4627 4628 const Int &operator--(Int &val) // Pre-decrement 4629 { 4630 val -= 1; 4631 return val; 4632 } 4633 4634 RValue<Bool> operator<(RValue<Int> lhs, RValue<Int> rhs) 4635 { 4636 return RValue<Bool>(Nucleus::createICmpSLT(lhs.value, rhs.value)); 4637 } 4638 4639 RValue<Bool> operator<=(RValue<Int> lhs, RValue<Int> rhs) 4640 { 4641 return RValue<Bool>(Nucleus::createICmpSLE(lhs.value, rhs.value)); 4642 } 4643 4644 RValue<Bool> operator>(RValue<Int> lhs, RValue<Int> rhs) 4645 { 4646 return RValue<Bool>(Nucleus::createICmpSGT(lhs.value, rhs.value)); 4647 } 4648 4649 RValue<Bool> operator>=(RValue<Int> lhs, RValue<Int> rhs) 4650 { 4651 return RValue<Bool>(Nucleus::createICmpSGE(lhs.value, rhs.value)); 4652 } 4653 4654 RValue<Bool> operator!=(RValue<Int> lhs, RValue<Int> rhs) 4655 { 4656 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 4657 } 4658 4659 RValue<Bool> operator==(RValue<Int> lhs, RValue<Int> rhs) 4660 { 4661 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 4662 } 4663 4664 RValue<Int> Max(RValue<Int> x, RValue<Int> y) 4665 { 4666 return IfThenElse(x > y, x, y); 4667 } 4668 4669 RValue<Int> Min(RValue<Int> x, RValue<Int> y) 4670 { 4671 return IfThenElse(x < y, x, y); 4672 } 4673 4674 RValue<Int> Clamp(RValue<Int> x, RValue<Int> min, RValue<Int> max) 4675 { 4676 return Min(Max(x, min), max); 4677 } 4678 4679 RValue<Int> RoundInt(RValue<Float> cast) 4680 { 4681 if(emulateIntrinsics || CPUID::ARM) 4682 { 4683 // Push the fractional part off the mantissa. Accurate up to +/-2^22. 4684 return Int((cast + Float(0x00C00000)) - Float(0x00C00000)); 4685 } 4686 else 4687 { 4688 Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); 4689 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 4690 auto target = ::context->getConstantUndef(Ice::IceType_i32); 4691 auto nearbyint = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 4692 nearbyint->addArg(cast.value); 4693 ::basicBlock->appendInst(nearbyint); 4694 4695 return RValue<Int>(V(result)); 4696 } 4697 } 4698 4699 Type *Int::getType() 4700 { 4701 return T(Ice::IceType_i32); 4702 } 4703 4704 Long::Long(RValue<Int> cast) 4705 { 4706 Value *integer = Nucleus::createSExt(cast.value, Long::getType()); 4707 4708 storeValue(integer); 4709 } 4710 4711 Long::Long(RValue<UInt> cast) 4712 { 4713 Value *integer = Nucleus::createZExt(cast.value, Long::getType()); 4714 4715 storeValue(integer); 4716 } 4717 4718 Long::Long(RValue<Long> rhs) 4719 { 4720 storeValue(rhs.value); 4721 } 4722 4723 RValue<Long> Long::operator=(int64_t rhs) 4724 { 4725 return RValue<Long>(storeValue(Nucleus::createConstantLong(rhs))); 4726 } 4727 4728 RValue<Long> Long::operator=(RValue<Long> rhs) 4729 { 4730 storeValue(rhs.value); 4731 4732 return rhs; 4733 } 4734 4735 RValue<Long> Long::operator=(const Long &rhs) 4736 { 4737 Value *value = rhs.loadValue(); 4738 storeValue(value); 4739 4740 return RValue<Long>(value); 4741 } 4742 4743 RValue<Long> Long::operator=(const Reference<Long> &rhs) 4744 { 4745 Value *value = rhs.loadValue(); 4746 storeValue(value); 4747 4748 return RValue<Long>(value); 4749 } 4750 4751 RValue<Long> operator+(RValue<Long> lhs, RValue<Long> rhs) 4752 { 4753 return RValue<Long>(Nucleus::createAdd(lhs.value, rhs.value)); 4754 } 4755 4756 RValue<Long> operator-(RValue<Long> lhs, RValue<Long> rhs) 4757 { 4758 return RValue<Long>(Nucleus::createSub(lhs.value, rhs.value)); 4759 } 4760 4761 RValue<Long> operator+=(Long &lhs, RValue<Long> rhs) 4762 { 4763 return lhs = lhs + rhs; 4764 } 4765 4766 RValue<Long> operator-=(Long &lhs, RValue<Long> rhs) 4767 { 4768 return lhs = lhs - rhs; 4769 } 4770 4771 RValue<Long> AddAtomic(RValue<Pointer<Long> > x, RValue<Long> y) 4772 { 4773 return RValue<Long>(Nucleus::createAtomicAdd(x.value, y.value)); 4774 } 4775 4776 Type *Long::getType() 4777 { 4778 return T(Ice::IceType_i64); 4779 } 4780 4781 UInt::UInt(Argument<UInt> argument) 4782 { 4783 storeValue(argument.value); 4784 } 4785 4786 UInt::UInt(RValue<UShort> cast) 4787 { 4788 Value *integer = Nucleus::createZExt(cast.value, UInt::getType()); 4789 4790 storeValue(integer); 4791 } 4792 4793 UInt::UInt(RValue<Long> cast) 4794 { 4795 Value *integer = Nucleus::createTrunc(cast.value, UInt::getType()); 4796 4797 storeValue(integer); 4798 } 4799 4800 UInt::UInt(RValue<Float> cast) 4801 { 4802 // Smallest positive value representable in UInt, but not in Int 4803 const unsigned int ustart = 0x80000000u; 4804 const float ustartf = float(ustart); 4805 4806 // If the value is negative, store 0, otherwise store the result of the conversion 4807 storeValue((~(As<Int>(cast) >> 31) & 4808 // Check if the value can be represented as an Int 4809 IfThenElse(cast >= ustartf, 4810 // If the value is too large, subtract ustart and re-add it after conversion. 4811 As<Int>(As<UInt>(Int(cast - Float(ustartf))) + UInt(ustart)), 4812 // Otherwise, just convert normally 4813 Int(cast))).value); 4814 } 4815 4816 UInt::UInt(int x) 4817 { 4818 storeValue(Nucleus::createConstantInt(x)); 4819 } 4820 4821 UInt::UInt(unsigned int x) 4822 { 4823 storeValue(Nucleus::createConstantInt(x)); 4824 } 4825 4826 UInt::UInt(RValue<UInt> rhs) 4827 { 4828 storeValue(rhs.value); 4829 } 4830 4831 UInt::UInt(RValue<Int> rhs) 4832 { 4833 storeValue(rhs.value); 4834 } 4835 4836 UInt::UInt(const UInt &rhs) 4837 { 4838 Value *value = rhs.loadValue(); 4839 storeValue(value); 4840 } 4841 4842 UInt::UInt(const Reference<UInt> &rhs) 4843 { 4844 Value *value = rhs.loadValue(); 4845 storeValue(value); 4846 } 4847 4848 UInt::UInt(const Int &rhs) 4849 { 4850 Value *value = rhs.loadValue(); 4851 storeValue(value); 4852 } 4853 4854 UInt::UInt(const Reference<Int> &rhs) 4855 { 4856 Value *value = rhs.loadValue(); 4857 storeValue(value); 4858 } 4859 4860 RValue<UInt> UInt::operator=(unsigned int rhs) 4861 { 4862 return RValue<UInt>(storeValue(Nucleus::createConstantInt(rhs))); 4863 } 4864 4865 RValue<UInt> UInt::operator=(RValue<UInt> rhs) 4866 { 4867 storeValue(rhs.value); 4868 4869 return rhs; 4870 } 4871 4872 RValue<UInt> UInt::operator=(RValue<Int> rhs) 4873 { 4874 storeValue(rhs.value); 4875 4876 return RValue<UInt>(rhs); 4877 } 4878 4879 RValue<UInt> UInt::operator=(const UInt &rhs) 4880 { 4881 Value *value = rhs.loadValue(); 4882 storeValue(value); 4883 4884 return RValue<UInt>(value); 4885 } 4886 4887 RValue<UInt> UInt::operator=(const Reference<UInt> &rhs) 4888 { 4889 Value *value = rhs.loadValue(); 4890 storeValue(value); 4891 4892 return RValue<UInt>(value); 4893 } 4894 4895 RValue<UInt> UInt::operator=(const Int &rhs) 4896 { 4897 Value *value = rhs.loadValue(); 4898 storeValue(value); 4899 4900 return RValue<UInt>(value); 4901 } 4902 4903 RValue<UInt> UInt::operator=(const Reference<Int> &rhs) 4904 { 4905 Value *value = rhs.loadValue(); 4906 storeValue(value); 4907 4908 return RValue<UInt>(value); 4909 } 4910 4911 RValue<UInt> operator+(RValue<UInt> lhs, RValue<UInt> rhs) 4912 { 4913 return RValue<UInt>(Nucleus::createAdd(lhs.value, rhs.value)); 4914 } 4915 4916 RValue<UInt> operator-(RValue<UInt> lhs, RValue<UInt> rhs) 4917 { 4918 return RValue<UInt>(Nucleus::createSub(lhs.value, rhs.value)); 4919 } 4920 4921 RValue<UInt> operator*(RValue<UInt> lhs, RValue<UInt> rhs) 4922 { 4923 return RValue<UInt>(Nucleus::createMul(lhs.value, rhs.value)); 4924 } 4925 4926 RValue<UInt> operator/(RValue<UInt> lhs, RValue<UInt> rhs) 4927 { 4928 return RValue<UInt>(Nucleus::createUDiv(lhs.value, rhs.value)); 4929 } 4930 4931 RValue<UInt> operator%(RValue<UInt> lhs, RValue<UInt> rhs) 4932 { 4933 return RValue<UInt>(Nucleus::createURem(lhs.value, rhs.value)); 4934 } 4935 4936 RValue<UInt> operator&(RValue<UInt> lhs, RValue<UInt> rhs) 4937 { 4938 return RValue<UInt>(Nucleus::createAnd(lhs.value, rhs.value)); 4939 } 4940 4941 RValue<UInt> operator|(RValue<UInt> lhs, RValue<UInt> rhs) 4942 { 4943 return RValue<UInt>(Nucleus::createOr(lhs.value, rhs.value)); 4944 } 4945 4946 RValue<UInt> operator^(RValue<UInt> lhs, RValue<UInt> rhs) 4947 { 4948 return RValue<UInt>(Nucleus::createXor(lhs.value, rhs.value)); 4949 } 4950 4951 RValue<UInt> operator<<(RValue<UInt> lhs, RValue<UInt> rhs) 4952 { 4953 return RValue<UInt>(Nucleus::createShl(lhs.value, rhs.value)); 4954 } 4955 4956 RValue<UInt> operator>>(RValue<UInt> lhs, RValue<UInt> rhs) 4957 { 4958 return RValue<UInt>(Nucleus::createLShr(lhs.value, rhs.value)); 4959 } 4960 4961 RValue<UInt> operator+=(UInt &lhs, RValue<UInt> rhs) 4962 { 4963 return lhs = lhs + rhs; 4964 } 4965 4966 RValue<UInt> operator-=(UInt &lhs, RValue<UInt> rhs) 4967 { 4968 return lhs = lhs - rhs; 4969 } 4970 4971 RValue<UInt> operator*=(UInt &lhs, RValue<UInt> rhs) 4972 { 4973 return lhs = lhs * rhs; 4974 } 4975 4976 RValue<UInt> operator/=(UInt &lhs, RValue<UInt> rhs) 4977 { 4978 return lhs = lhs / rhs; 4979 } 4980 4981 RValue<UInt> operator%=(UInt &lhs, RValue<UInt> rhs) 4982 { 4983 return lhs = lhs % rhs; 4984 } 4985 4986 RValue<UInt> operator&=(UInt &lhs, RValue<UInt> rhs) 4987 { 4988 return lhs = lhs & rhs; 4989 } 4990 4991 RValue<UInt> operator|=(UInt &lhs, RValue<UInt> rhs) 4992 { 4993 return lhs = lhs | rhs; 4994 } 4995 4996 RValue<UInt> operator^=(UInt &lhs, RValue<UInt> rhs) 4997 { 4998 return lhs = lhs ^ rhs; 4999 } 5000 5001 RValue<UInt> operator<<=(UInt &lhs, RValue<UInt> rhs) 5002 { 5003 return lhs = lhs << rhs; 5004 } 5005 5006 RValue<UInt> operator>>=(UInt &lhs, RValue<UInt> rhs) 5007 { 5008 return lhs = lhs >> rhs; 5009 } 5010 5011 RValue<UInt> operator+(RValue<UInt> val) 5012 { 5013 return val; 5014 } 5015 5016 RValue<UInt> operator-(RValue<UInt> val) 5017 { 5018 return RValue<UInt>(Nucleus::createNeg(val.value)); 5019 } 5020 5021 RValue<UInt> operator~(RValue<UInt> val) 5022 { 5023 return RValue<UInt>(Nucleus::createNot(val.value)); 5024 } 5025 5026 RValue<UInt> operator++(UInt &val, int) // Post-increment 5027 { 5028 RValue<UInt> res = val; 5029 val += 1; 5030 return res; 5031 } 5032 5033 const UInt &operator++(UInt &val) // Pre-increment 5034 { 5035 val += 1; 5036 return val; 5037 } 5038 5039 RValue<UInt> operator--(UInt &val, int) // Post-decrement 5040 { 5041 RValue<UInt> res = val; 5042 val -= 1; 5043 return res; 5044 } 5045 5046 const UInt &operator--(UInt &val) // Pre-decrement 5047 { 5048 val -= 1; 5049 return val; 5050 } 5051 5052 RValue<UInt> Max(RValue<UInt> x, RValue<UInt> y) 5053 { 5054 return IfThenElse(x > y, x, y); 5055 } 5056 5057 RValue<UInt> Min(RValue<UInt> x, RValue<UInt> y) 5058 { 5059 return IfThenElse(x < y, x, y); 5060 } 5061 5062 RValue<UInt> Clamp(RValue<UInt> x, RValue<UInt> min, RValue<UInt> max) 5063 { 5064 return Min(Max(x, min), max); 5065 } 5066 5067 RValue<Bool> operator<(RValue<UInt> lhs, RValue<UInt> rhs) 5068 { 5069 return RValue<Bool>(Nucleus::createICmpULT(lhs.value, rhs.value)); 5070 } 5071 5072 RValue<Bool> operator<=(RValue<UInt> lhs, RValue<UInt> rhs) 5073 { 5074 return RValue<Bool>(Nucleus::createICmpULE(lhs.value, rhs.value)); 5075 } 5076 5077 RValue<Bool> operator>(RValue<UInt> lhs, RValue<UInt> rhs) 5078 { 5079 return RValue<Bool>(Nucleus::createICmpUGT(lhs.value, rhs.value)); 5080 } 5081 5082 RValue<Bool> operator>=(RValue<UInt> lhs, RValue<UInt> rhs) 5083 { 5084 return RValue<Bool>(Nucleus::createICmpUGE(lhs.value, rhs.value)); 5085 } 5086 5087 RValue<Bool> operator!=(RValue<UInt> lhs, RValue<UInt> rhs) 5088 { 5089 return RValue<Bool>(Nucleus::createICmpNE(lhs.value, rhs.value)); 5090 } 5091 5092 RValue<Bool> operator==(RValue<UInt> lhs, RValue<UInt> rhs) 5093 { 5094 return RValue<Bool>(Nucleus::createICmpEQ(lhs.value, rhs.value)); 5095 } 5096 5097 // RValue<UInt> RoundUInt(RValue<Float> cast) 5098 // { 5099 // assert(false && "UNIMPLEMENTED"); return RValue<UInt>(V(nullptr)); 5100 // } 5101 5102 Type *UInt::getType() 5103 { 5104 return T(Ice::IceType_i32); 5105 } 5106 5107 // Int2::Int2(RValue<Int> cast) 5108 // { 5109 // Value *extend = Nucleus::createZExt(cast.value, Long::getType()); 5110 // Value *vector = Nucleus::createBitCast(extend, Int2::getType()); 5111 // 5112 // Constant *shuffle[2]; 5113 // shuffle[0] = Nucleus::createConstantInt(0); 5114 // shuffle[1] = Nucleus::createConstantInt(0); 5115 // 5116 // Value *replicate = Nucleus::createShuffleVector(vector, UndefValue::get(Int2::getType()), Nucleus::createConstantVector(shuffle, 2)); 5117 // 5118 // storeValue(replicate); 5119 // } 5120 5121 Int2::Int2(RValue<Int4> cast) 5122 { 5123 storeValue(Nucleus::createBitCast(cast.value, getType())); 5124 } 5125 5126 Int2::Int2(int x, int y) 5127 { 5128 int64_t constantVector[2] = {x, y}; 5129 storeValue(Nucleus::createConstantVector(constantVector, getType())); 5130 } 5131 5132 Int2::Int2(RValue<Int2> rhs) 5133 { 5134 storeValue(rhs.value); 5135 } 5136 5137 Int2::Int2(const Int2 &rhs) 5138 { 5139 Value *value = rhs.loadValue(); 5140 storeValue(value); 5141 } 5142 5143 Int2::Int2(const Reference<Int2> &rhs) 5144 { 5145 Value *value = rhs.loadValue(); 5146 storeValue(value); 5147 } 5148 5149 Int2::Int2(RValue<Int> lo, RValue<Int> hi) 5150 { 5151 int shuffle[4] = {0, 4, 1, 5}; 5152 Value *packed = Nucleus::createShuffleVector(Int4(lo).loadValue(), Int4(hi).loadValue(), shuffle); 5153 5154 storeValue(Nucleus::createBitCast(packed, Int2::getType())); 5155 } 5156 5157 RValue<Int2> Int2::operator=(RValue<Int2> rhs) 5158 { 5159 storeValue(rhs.value); 5160 5161 return rhs; 5162 } 5163 5164 RValue<Int2> Int2::operator=(const Int2 &rhs) 5165 { 5166 Value *value = rhs.loadValue(); 5167 storeValue(value); 5168 5169 return RValue<Int2>(value); 5170 } 5171 5172 RValue<Int2> Int2::operator=(const Reference<Int2> &rhs) 5173 { 5174 Value *value = rhs.loadValue(); 5175 storeValue(value); 5176 5177 return RValue<Int2>(value); 5178 } 5179 5180 RValue<Int2> operator+(RValue<Int2> lhs, RValue<Int2> rhs) 5181 { 5182 return RValue<Int2>(Nucleus::createAdd(lhs.value, rhs.value)); 5183 } 5184 5185 RValue<Int2> operator-(RValue<Int2> lhs, RValue<Int2> rhs) 5186 { 5187 return RValue<Int2>(Nucleus::createSub(lhs.value, rhs.value)); 5188 } 5189 5190 // RValue<Int2> operator*(RValue<Int2> lhs, RValue<Int2> rhs) 5191 // { 5192 // return RValue<Int2>(Nucleus::createMul(lhs.value, rhs.value)); 5193 // } 5194 5195 // RValue<Int2> operator/(RValue<Int2> lhs, RValue<Int2> rhs) 5196 // { 5197 // return RValue<Int2>(Nucleus::createSDiv(lhs.value, rhs.value)); 5198 // } 5199 5200 // RValue<Int2> operator%(RValue<Int2> lhs, RValue<Int2> rhs) 5201 // { 5202 // return RValue<Int2>(Nucleus::createSRem(lhs.value, rhs.value)); 5203 // } 5204 5205 RValue<Int2> operator&(RValue<Int2> lhs, RValue<Int2> rhs) 5206 { 5207 return RValue<Int2>(Nucleus::createAnd(lhs.value, rhs.value)); 5208 } 5209 5210 RValue<Int2> operator|(RValue<Int2> lhs, RValue<Int2> rhs) 5211 { 5212 return RValue<Int2>(Nucleus::createOr(lhs.value, rhs.value)); 5213 } 5214 5215 RValue<Int2> operator^(RValue<Int2> lhs, RValue<Int2> rhs) 5216 { 5217 return RValue<Int2>(Nucleus::createXor(lhs.value, rhs.value)); 5218 } 5219 5220 RValue<Int2> operator<<(RValue<Int2> lhs, unsigned char rhs) 5221 { 5222 if(emulateIntrinsics) 5223 { 5224 Int2 result; 5225 result = Insert(result, Extract(lhs, 0) << Int(rhs), 0); 5226 result = Insert(result, Extract(lhs, 1) << Int(rhs), 1); 5227 5228 return result; 5229 } 5230 else 5231 { 5232 return RValue<Int2>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 5233 } 5234 } 5235 5236 RValue<Int2> operator>>(RValue<Int2> lhs, unsigned char rhs) 5237 { 5238 if(emulateIntrinsics) 5239 { 5240 Int2 result; 5241 result = Insert(result, Extract(lhs, 0) >> Int(rhs), 0); 5242 result = Insert(result, Extract(lhs, 1) >> Int(rhs), 1); 5243 5244 return result; 5245 } 5246 else 5247 { 5248 return RValue<Int2>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 5249 } 5250 } 5251 5252 RValue<Int2> operator+=(Int2 &lhs, RValue<Int2> rhs) 5253 { 5254 return lhs = lhs + rhs; 5255 } 5256 5257 RValue<Int2> operator-=(Int2 &lhs, RValue<Int2> rhs) 5258 { 5259 return lhs = lhs - rhs; 5260 } 5261 5262 // RValue<Int2> operator*=(Int2 &lhs, RValue<Int2> rhs) 5263 // { 5264 // return lhs = lhs * rhs; 5265 // } 5266 5267 // RValue<Int2> operator/=(Int2 &lhs, RValue<Int2> rhs) 5268 // { 5269 // return lhs = lhs / rhs; 5270 // } 5271 5272 // RValue<Int2> operator%=(Int2 &lhs, RValue<Int2> rhs) 5273 // { 5274 // return lhs = lhs % rhs; 5275 // } 5276 5277 RValue<Int2> operator&=(Int2 &lhs, RValue<Int2> rhs) 5278 { 5279 return lhs = lhs & rhs; 5280 } 5281 5282 RValue<Int2> operator|=(Int2 &lhs, RValue<Int2> rhs) 5283 { 5284 return lhs = lhs | rhs; 5285 } 5286 5287 RValue<Int2> operator^=(Int2 &lhs, RValue<Int2> rhs) 5288 { 5289 return lhs = lhs ^ rhs; 5290 } 5291 5292 RValue<Int2> operator<<=(Int2 &lhs, unsigned char rhs) 5293 { 5294 return lhs = lhs << rhs; 5295 } 5296 5297 RValue<Int2> operator>>=(Int2 &lhs, unsigned char rhs) 5298 { 5299 return lhs = lhs >> rhs; 5300 } 5301 5302 // RValue<Int2> operator+(RValue<Int2> val) 5303 // { 5304 // return val; 5305 // } 5306 5307 // RValue<Int2> operator-(RValue<Int2> val) 5308 // { 5309 // return RValue<Int2>(Nucleus::createNeg(val.value)); 5310 // } 5311 5312 RValue<Int2> operator~(RValue<Int2> val) 5313 { 5314 return RValue<Int2>(Nucleus::createNot(val.value)); 5315 } 5316 5317 RValue<Short4> UnpackLow(RValue<Int2> x, RValue<Int2> y) 5318 { 5319 int shuffle[4] = {0, 4, 1, 5}; // Real type is v4i32 5320 return As<Short4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 5321 } 5322 5323 RValue<Short4> UnpackHigh(RValue<Int2> x, RValue<Int2> y) 5324 { 5325 int shuffle[4] = {0, 4, 1, 5}; // Real type is v4i32 5326 auto lowHigh = RValue<Int4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 5327 return As<Short4>(Swizzle(lowHigh, 0xEE)); 5328 } 5329 5330 RValue<Int> Extract(RValue<Int2> val, int i) 5331 { 5332 return RValue<Int>(Nucleus::createExtractElement(val.value, Int::getType(), i)); 5333 } 5334 5335 RValue<Int2> Insert(RValue<Int2> val, RValue<Int> element, int i) 5336 { 5337 return RValue<Int2>(Nucleus::createInsertElement(val.value, element.value, i)); 5338 } 5339 5340 Type *Int2::getType() 5341 { 5342 return T(Type_v2i32); 5343 } 5344 5345 UInt2::UInt2(unsigned int x, unsigned int y) 5346 { 5347 int64_t constantVector[2] = {x, y}; 5348 storeValue(Nucleus::createConstantVector(constantVector, getType())); 5349 } 5350 5351 UInt2::UInt2(RValue<UInt2> rhs) 5352 { 5353 storeValue(rhs.value); 5354 } 5355 5356 UInt2::UInt2(const UInt2 &rhs) 5357 { 5358 Value *value = rhs.loadValue(); 5359 storeValue(value); 5360 } 5361 5362 UInt2::UInt2(const Reference<UInt2> &rhs) 5363 { 5364 Value *value = rhs.loadValue(); 5365 storeValue(value); 5366 } 5367 5368 RValue<UInt2> UInt2::operator=(RValue<UInt2> rhs) 5369 { 5370 storeValue(rhs.value); 5371 5372 return rhs; 5373 } 5374 5375 RValue<UInt2> UInt2::operator=(const UInt2 &rhs) 5376 { 5377 Value *value = rhs.loadValue(); 5378 storeValue(value); 5379 5380 return RValue<UInt2>(value); 5381 } 5382 5383 RValue<UInt2> UInt2::operator=(const Reference<UInt2> &rhs) 5384 { 5385 Value *value = rhs.loadValue(); 5386 storeValue(value); 5387 5388 return RValue<UInt2>(value); 5389 } 5390 5391 RValue<UInt2> operator+(RValue<UInt2> lhs, RValue<UInt2> rhs) 5392 { 5393 return RValue<UInt2>(Nucleus::createAdd(lhs.value, rhs.value)); 5394 } 5395 5396 RValue<UInt2> operator-(RValue<UInt2> lhs, RValue<UInt2> rhs) 5397 { 5398 return RValue<UInt2>(Nucleus::createSub(lhs.value, rhs.value)); 5399 } 5400 5401 // RValue<UInt2> operator*(RValue<UInt2> lhs, RValue<UInt2> rhs) 5402 // { 5403 // return RValue<UInt2>(Nucleus::createMul(lhs.value, rhs.value)); 5404 // } 5405 5406 // RValue<UInt2> operator/(RValue<UInt2> lhs, RValue<UInt2> rhs) 5407 // { 5408 // return RValue<UInt2>(Nucleus::createUDiv(lhs.value, rhs.value)); 5409 // } 5410 5411 // RValue<UInt2> operator%(RValue<UInt2> lhs, RValue<UInt2> rhs) 5412 // { 5413 // return RValue<UInt2>(Nucleus::createURem(lhs.value, rhs.value)); 5414 // } 5415 5416 RValue<UInt2> operator&(RValue<UInt2> lhs, RValue<UInt2> rhs) 5417 { 5418 return RValue<UInt2>(Nucleus::createAnd(lhs.value, rhs.value)); 5419 } 5420 5421 RValue<UInt2> operator|(RValue<UInt2> lhs, RValue<UInt2> rhs) 5422 { 5423 return RValue<UInt2>(Nucleus::createOr(lhs.value, rhs.value)); 5424 } 5425 5426 RValue<UInt2> operator^(RValue<UInt2> lhs, RValue<UInt2> rhs) 5427 { 5428 return RValue<UInt2>(Nucleus::createXor(lhs.value, rhs.value)); 5429 } 5430 5431 RValue<UInt> Extract(RValue<UInt2> val, int i) 5432 { 5433 return RValue<UInt>(Nucleus::createExtractElement(val.value, UInt::getType(), i)); 5434 } 5435 5436 RValue<UInt2> Insert(RValue<UInt2> val, RValue<UInt> element, int i) 5437 { 5438 return RValue<UInt2>(Nucleus::createInsertElement(val.value, element.value, i)); 5439 } 5440 5441 RValue<UInt2> operator<<(RValue<UInt2> lhs, unsigned char rhs) 5442 { 5443 if(emulateIntrinsics) 5444 { 5445 UInt2 result; 5446 result = Insert(result, Extract(lhs, 0) << UInt(rhs), 0); 5447 result = Insert(result, Extract(lhs, 1) << UInt(rhs), 1); 5448 5449 return result; 5450 } 5451 else 5452 { 5453 return RValue<UInt2>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 5454 } 5455 } 5456 5457 RValue<UInt2> operator>>(RValue<UInt2> lhs, unsigned char rhs) 5458 { 5459 if(emulateIntrinsics) 5460 { 5461 UInt2 result; 5462 result = Insert(result, Extract(lhs, 0) >> UInt(rhs), 0); 5463 result = Insert(result, Extract(lhs, 1) >> UInt(rhs), 1); 5464 5465 return result; 5466 } 5467 else 5468 { 5469 return RValue<UInt2>(Nucleus::createLShr(lhs.value, V(::context->getConstantInt32(rhs)))); 5470 } 5471 } 5472 5473 RValue<UInt2> operator+=(UInt2 &lhs, RValue<UInt2> rhs) 5474 { 5475 return lhs = lhs + rhs; 5476 } 5477 5478 RValue<UInt2> operator-=(UInt2 &lhs, RValue<UInt2> rhs) 5479 { 5480 return lhs = lhs - rhs; 5481 } 5482 5483 // RValue<UInt2> operator*=(UInt2 &lhs, RValue<UInt2> rhs) 5484 // { 5485 // return lhs = lhs * rhs; 5486 // } 5487 5488 // RValue<UInt2> operator/=(UInt2 &lhs, RValue<UInt2> rhs) 5489 // { 5490 // return lhs = lhs / rhs; 5491 // } 5492 5493 // RValue<UInt2> operator%=(UInt2 &lhs, RValue<UInt2> rhs) 5494 // { 5495 // return lhs = lhs % rhs; 5496 // } 5497 5498 RValue<UInt2> operator&=(UInt2 &lhs, RValue<UInt2> rhs) 5499 { 5500 return lhs = lhs & rhs; 5501 } 5502 5503 RValue<UInt2> operator|=(UInt2 &lhs, RValue<UInt2> rhs) 5504 { 5505 return lhs = lhs | rhs; 5506 } 5507 5508 RValue<UInt2> operator^=(UInt2 &lhs, RValue<UInt2> rhs) 5509 { 5510 return lhs = lhs ^ rhs; 5511 } 5512 5513 RValue<UInt2> operator<<=(UInt2 &lhs, unsigned char rhs) 5514 { 5515 return lhs = lhs << rhs; 5516 } 5517 5518 RValue<UInt2> operator>>=(UInt2 &lhs, unsigned char rhs) 5519 { 5520 return lhs = lhs >> rhs; 5521 } 5522 5523 // RValue<UInt2> operator+(RValue<UInt2> val) 5524 // { 5525 // return val; 5526 // } 5527 5528 // RValue<UInt2> operator-(RValue<UInt2> val) 5529 // { 5530 // return RValue<UInt2>(Nucleus::createNeg(val.value)); 5531 // } 5532 5533 RValue<UInt2> operator~(RValue<UInt2> val) 5534 { 5535 return RValue<UInt2>(Nucleus::createNot(val.value)); 5536 } 5537 5538 Type *UInt2::getType() 5539 { 5540 return T(Type_v2i32); 5541 } 5542 5543 Int4::Int4() : XYZW(this) 5544 { 5545 } 5546 5547 Int4::Int4(RValue<Byte4> cast) : XYZW(this) 5548 { 5549 Value *x = Nucleus::createBitCast(cast.value, Int::getType()); 5550 Value *a = Nucleus::createInsertElement(loadValue(), x, 0); 5551 5552 Value *e; 5553 int swizzle[16] = {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}; 5554 Value *b = Nucleus::createBitCast(a, Byte16::getType()); 5555 Value *c = Nucleus::createShuffleVector(b, V(Nucleus::createNullValue(Byte16::getType())), swizzle); 5556 5557 int swizzle2[8] = {0, 8, 1, 9, 2, 10, 3, 11}; 5558 Value *d = Nucleus::createBitCast(c, Short8::getType()); 5559 e = Nucleus::createShuffleVector(d, V(Nucleus::createNullValue(Short8::getType())), swizzle2); 5560 5561 Value *f = Nucleus::createBitCast(e, Int4::getType()); 5562 storeValue(f); 5563 } 5564 5565 Int4::Int4(RValue<SByte4> cast) : XYZW(this) 5566 { 5567 Value *x = Nucleus::createBitCast(cast.value, Int::getType()); 5568 Value *a = Nucleus::createInsertElement(loadValue(), x, 0); 5569 5570 int swizzle[16] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; 5571 Value *b = Nucleus::createBitCast(a, Byte16::getType()); 5572 Value *c = Nucleus::createShuffleVector(b, b, swizzle); 5573 5574 int swizzle2[8] = {0, 0, 1, 1, 2, 2, 3, 3}; 5575 Value *d = Nucleus::createBitCast(c, Short8::getType()); 5576 Value *e = Nucleus::createShuffleVector(d, d, swizzle2); 5577 5578 *this = As<Int4>(e) >> 24; 5579 } 5580 5581 Int4::Int4(RValue<Float4> cast) : XYZW(this) 5582 { 5583 Value *xyzw = Nucleus::createFPToSI(cast.value, Int4::getType()); 5584 5585 storeValue(xyzw); 5586 } 5587 5588 Int4::Int4(RValue<Short4> cast) : XYZW(this) 5589 { 5590 int swizzle[8] = {0, 0, 1, 1, 2, 2, 3, 3}; 5591 Value *c = Nucleus::createShuffleVector(cast.value, cast.value, swizzle); 5592 5593 *this = As<Int4>(c) >> 16; 5594 } 5595 5596 Int4::Int4(RValue<UShort4> cast) : XYZW(this) 5597 { 5598 int swizzle[8] = {0, 8, 1, 9, 2, 10, 3, 11}; 5599 Value *c = Nucleus::createShuffleVector(cast.value, Short8(0, 0, 0, 0, 0, 0, 0, 0).loadValue(), swizzle); 5600 Value *d = Nucleus::createBitCast(c, Int4::getType()); 5601 storeValue(d); 5602 } 5603 5604 Int4::Int4(int xyzw) : XYZW(this) 5605 { 5606 constant(xyzw, xyzw, xyzw, xyzw); 5607 } 5608 5609 Int4::Int4(int x, int yzw) : XYZW(this) 5610 { 5611 constant(x, yzw, yzw, yzw); 5612 } 5613 5614 Int4::Int4(int x, int y, int zw) : XYZW(this) 5615 { 5616 constant(x, y, zw, zw); 5617 } 5618 5619 Int4::Int4(int x, int y, int z, int w) : XYZW(this) 5620 { 5621 constant(x, y, z, w); 5622 } 5623 5624 void Int4::constant(int x, int y, int z, int w) 5625 { 5626 int64_t constantVector[4] = {x, y, z, w}; 5627 storeValue(Nucleus::createConstantVector(constantVector, getType())); 5628 } 5629 5630 Int4::Int4(RValue<Int4> rhs) : XYZW(this) 5631 { 5632 storeValue(rhs.value); 5633 } 5634 5635 Int4::Int4(const Int4 &rhs) : XYZW(this) 5636 { 5637 Value *value = rhs.loadValue(); 5638 storeValue(value); 5639 } 5640 5641 Int4::Int4(const Reference<Int4> &rhs) : XYZW(this) 5642 { 5643 Value *value = rhs.loadValue(); 5644 storeValue(value); 5645 } 5646 5647 Int4::Int4(RValue<UInt4> rhs) : XYZW(this) 5648 { 5649 storeValue(rhs.value); 5650 } 5651 5652 Int4::Int4(const UInt4 &rhs) : XYZW(this) 5653 { 5654 Value *value = rhs.loadValue(); 5655 storeValue(value); 5656 } 5657 5658 Int4::Int4(const Reference<UInt4> &rhs) : XYZW(this) 5659 { 5660 Value *value = rhs.loadValue(); 5661 storeValue(value); 5662 } 5663 5664 Int4::Int4(RValue<Int2> lo, RValue<Int2> hi) : XYZW(this) 5665 { 5666 int shuffle[4] = {0, 1, 4, 5}; // Real type is v4i32 5667 Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle); 5668 5669 storeValue(packed); 5670 } 5671 5672 Int4::Int4(RValue<Int> rhs) : XYZW(this) 5673 { 5674 Value *vector = Nucleus::createBitCast(rhs.value, Int4::getType()); 5675 5676 int swizzle[4] = {0, 0, 0, 0}; 5677 Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle); 5678 5679 storeValue(replicate); 5680 } 5681 5682 Int4::Int4(const Int &rhs) : XYZW(this) 5683 { 5684 *this = RValue<Int>(rhs.loadValue()); 5685 } 5686 5687 Int4::Int4(const Reference<Int> &rhs) : XYZW(this) 5688 { 5689 *this = RValue<Int>(rhs.loadValue()); 5690 } 5691 5692 RValue<Int4> Int4::operator=(RValue<Int4> rhs) 5693 { 5694 storeValue(rhs.value); 5695 5696 return rhs; 5697 } 5698 5699 RValue<Int4> Int4::operator=(const Int4 &rhs) 5700 { 5701 Value *value = rhs.loadValue(); 5702 storeValue(value); 5703 5704 return RValue<Int4>(value); 5705 } 5706 5707 RValue<Int4> Int4::operator=(const Reference<Int4> &rhs) 5708 { 5709 Value *value = rhs.loadValue(); 5710 storeValue(value); 5711 5712 return RValue<Int4>(value); 5713 } 5714 5715 RValue<Int4> operator+(RValue<Int4> lhs, RValue<Int4> rhs) 5716 { 5717 return RValue<Int4>(Nucleus::createAdd(lhs.value, rhs.value)); 5718 } 5719 5720 RValue<Int4> operator-(RValue<Int4> lhs, RValue<Int4> rhs) 5721 { 5722 return RValue<Int4>(Nucleus::createSub(lhs.value, rhs.value)); 5723 } 5724 5725 RValue<Int4> operator*(RValue<Int4> lhs, RValue<Int4> rhs) 5726 { 5727 return RValue<Int4>(Nucleus::createMul(lhs.value, rhs.value)); 5728 } 5729 5730 RValue<Int4> operator/(RValue<Int4> lhs, RValue<Int4> rhs) 5731 { 5732 return RValue<Int4>(Nucleus::createSDiv(lhs.value, rhs.value)); 5733 } 5734 5735 RValue<Int4> operator%(RValue<Int4> lhs, RValue<Int4> rhs) 5736 { 5737 return RValue<Int4>(Nucleus::createSRem(lhs.value, rhs.value)); 5738 } 5739 5740 RValue<Int4> operator&(RValue<Int4> lhs, RValue<Int4> rhs) 5741 { 5742 return RValue<Int4>(Nucleus::createAnd(lhs.value, rhs.value)); 5743 } 5744 5745 RValue<Int4> operator|(RValue<Int4> lhs, RValue<Int4> rhs) 5746 { 5747 return RValue<Int4>(Nucleus::createOr(lhs.value, rhs.value)); 5748 } 5749 5750 RValue<Int4> operator^(RValue<Int4> lhs, RValue<Int4> rhs) 5751 { 5752 return RValue<Int4>(Nucleus::createXor(lhs.value, rhs.value)); 5753 } 5754 5755 RValue<Int4> operator<<(RValue<Int4> lhs, unsigned char rhs) 5756 { 5757 if(emulateIntrinsics) 5758 { 5759 Int4 result; 5760 result = Insert(result, Extract(lhs, 0) << Int(rhs), 0); 5761 result = Insert(result, Extract(lhs, 1) << Int(rhs), 1); 5762 result = Insert(result, Extract(lhs, 2) << Int(rhs), 2); 5763 result = Insert(result, Extract(lhs, 3) << Int(rhs), 3); 5764 5765 return result; 5766 } 5767 else 5768 { 5769 return RValue<Int4>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 5770 } 5771 } 5772 5773 RValue<Int4> operator>>(RValue<Int4> lhs, unsigned char rhs) 5774 { 5775 if(emulateIntrinsics) 5776 { 5777 Int4 result; 5778 result = Insert(result, Extract(lhs, 0) >> Int(rhs), 0); 5779 result = Insert(result, Extract(lhs, 1) >> Int(rhs), 1); 5780 result = Insert(result, Extract(lhs, 2) >> Int(rhs), 2); 5781 result = Insert(result, Extract(lhs, 3) >> Int(rhs), 3); 5782 5783 return result; 5784 } 5785 else 5786 { 5787 return RValue<Int4>(Nucleus::createAShr(lhs.value, V(::context->getConstantInt32(rhs)))); 5788 } 5789 } 5790 5791 RValue<Int4> operator<<(RValue<Int4> lhs, RValue<Int4> rhs) 5792 { 5793 return RValue<Int4>(Nucleus::createShl(lhs.value, rhs.value)); 5794 } 5795 5796 RValue<Int4> operator>>(RValue<Int4> lhs, RValue<Int4> rhs) 5797 { 5798 return RValue<Int4>(Nucleus::createAShr(lhs.value, rhs.value)); 5799 } 5800 5801 RValue<Int4> operator+=(Int4 &lhs, RValue<Int4> rhs) 5802 { 5803 return lhs = lhs + rhs; 5804 } 5805 5806 RValue<Int4> operator-=(Int4 &lhs, RValue<Int4> rhs) 5807 { 5808 return lhs = lhs - rhs; 5809 } 5810 5811 RValue<Int4> operator*=(Int4 &lhs, RValue<Int4> rhs) 5812 { 5813 return lhs = lhs * rhs; 5814 } 5815 5816 // RValue<Int4> operator/=(Int4 &lhs, RValue<Int4> rhs) 5817 // { 5818 // return lhs = lhs / rhs; 5819 // } 5820 5821 // RValue<Int4> operator%=(Int4 &lhs, RValue<Int4> rhs) 5822 // { 5823 // return lhs = lhs % rhs; 5824 // } 5825 5826 RValue<Int4> operator&=(Int4 &lhs, RValue<Int4> rhs) 5827 { 5828 return lhs = lhs & rhs; 5829 } 5830 5831 RValue<Int4> operator|=(Int4 &lhs, RValue<Int4> rhs) 5832 { 5833 return lhs = lhs | rhs; 5834 } 5835 5836 RValue<Int4> operator^=(Int4 &lhs, RValue<Int4> rhs) 5837 { 5838 return lhs = lhs ^ rhs; 5839 } 5840 5841 RValue<Int4> operator<<=(Int4 &lhs, unsigned char rhs) 5842 { 5843 return lhs = lhs << rhs; 5844 } 5845 5846 RValue<Int4> operator>>=(Int4 &lhs, unsigned char rhs) 5847 { 5848 return lhs = lhs >> rhs; 5849 } 5850 5851 RValue<Int4> operator+(RValue<Int4> val) 5852 { 5853 return val; 5854 } 5855 5856 RValue<Int4> operator-(RValue<Int4> val) 5857 { 5858 return RValue<Int4>(Nucleus::createNeg(val.value)); 5859 } 5860 5861 RValue<Int4> operator~(RValue<Int4> val) 5862 { 5863 return RValue<Int4>(Nucleus::createNot(val.value)); 5864 } 5865 5866 RValue<Int4> CmpEQ(RValue<Int4> x, RValue<Int4> y) 5867 { 5868 return RValue<Int4>(Nucleus::createICmpEQ(x.value, y.value)); 5869 } 5870 5871 RValue<Int4> CmpLT(RValue<Int4> x, RValue<Int4> y) 5872 { 5873 return RValue<Int4>(Nucleus::createICmpSLT(x.value, y.value)); 5874 } 5875 5876 RValue<Int4> CmpLE(RValue<Int4> x, RValue<Int4> y) 5877 { 5878 return RValue<Int4>(Nucleus::createICmpSLE(x.value, y.value)); 5879 } 5880 5881 RValue<Int4> CmpNEQ(RValue<Int4> x, RValue<Int4> y) 5882 { 5883 return RValue<Int4>(Nucleus::createICmpNE(x.value, y.value)); 5884 } 5885 5886 RValue<Int4> CmpNLT(RValue<Int4> x, RValue<Int4> y) 5887 { 5888 return RValue<Int4>(Nucleus::createICmpSGE(x.value, y.value)); 5889 } 5890 5891 RValue<Int4> CmpNLE(RValue<Int4> x, RValue<Int4> y) 5892 { 5893 return RValue<Int4>(Nucleus::createICmpSGT(x.value, y.value)); 5894 } 5895 5896 RValue<Int4> Max(RValue<Int4> x, RValue<Int4> y) 5897 { 5898 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 5899 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value, y.value); 5900 ::basicBlock->appendInst(cmp); 5901 5902 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); 5903 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 5904 ::basicBlock->appendInst(select); 5905 5906 return RValue<Int4>(V(result)); 5907 } 5908 5909 RValue<Int4> Min(RValue<Int4> x, RValue<Int4> y) 5910 { 5911 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 5912 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value, y.value); 5913 ::basicBlock->appendInst(cmp); 5914 5915 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); 5916 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 5917 ::basicBlock->appendInst(select); 5918 5919 return RValue<Int4>(V(result)); 5920 } 5921 5922 RValue<Int4> RoundInt(RValue<Float4> cast) 5923 { 5924 if(emulateIntrinsics || CPUID::ARM) 5925 { 5926 // Push the fractional part off the mantissa. Accurate up to +/-2^22. 5927 return Int4((cast + Float4(0x00C00000)) - Float4(0x00C00000)); 5928 } 5929 else 5930 { 5931 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); 5932 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 5933 auto target = ::context->getConstantUndef(Ice::IceType_i32); 5934 auto nearbyint = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 5935 nearbyint->addArg(cast.value); 5936 ::basicBlock->appendInst(nearbyint); 5937 5938 return RValue<Int4>(V(result)); 5939 } 5940 } 5941 5942 RValue<Short8> PackSigned(RValue<Int4> x, RValue<Int4> y) 5943 { 5944 if(emulateIntrinsics) 5945 { 5946 Short8 result; 5947 result = Insert(result, SaturateSigned(Extract(x, 0)), 0); 5948 result = Insert(result, SaturateSigned(Extract(x, 1)), 1); 5949 result = Insert(result, SaturateSigned(Extract(x, 2)), 2); 5950 result = Insert(result, SaturateSigned(Extract(x, 3)), 3); 5951 result = Insert(result, SaturateSigned(Extract(y, 0)), 4); 5952 result = Insert(result, SaturateSigned(Extract(y, 1)), 5); 5953 result = Insert(result, SaturateSigned(Extract(y, 2)), 6); 5954 result = Insert(result, SaturateSigned(Extract(y, 3)), 7); 5955 5956 return result; 5957 } 5958 else 5959 { 5960 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 5961 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackSigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 5962 auto target = ::context->getConstantUndef(Ice::IceType_i32); 5963 auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 5964 pack->addArg(x.value); 5965 pack->addArg(y.value); 5966 ::basicBlock->appendInst(pack); 5967 5968 return RValue<Short8>(V(result)); 5969 } 5970 } 5971 5972 RValue<UShort8> PackUnsigned(RValue<Int4> x, RValue<Int4> y) 5973 { 5974 if(emulateIntrinsics || !(CPUID::SSE4_1 || CPUID::ARM)) 5975 { 5976 RValue<Int4> sx = As<Int4>(x); 5977 RValue<Int4> bx = (sx & ~(sx >> 31)) - Int4(0x8000); 5978 5979 RValue<Int4> sy = As<Int4>(y); 5980 RValue<Int4> by = (sy & ~(sy >> 31)) - Int4(0x8000); 5981 5982 return As<UShort8>(PackSigned(bx, by) + Short8(0x8000u)); 5983 } 5984 else 5985 { 5986 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); 5987 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 5988 auto target = ::context->getConstantUndef(Ice::IceType_i32); 5989 auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 5990 pack->addArg(x.value); 5991 pack->addArg(y.value); 5992 ::basicBlock->appendInst(pack); 5993 5994 return RValue<UShort8>(V(result)); 5995 } 5996 } 5997 5998 RValue<Int> Extract(RValue<Int4> x, int i) 5999 { 6000 return RValue<Int>(Nucleus::createExtractElement(x.value, Int::getType(), i)); 6001 } 6002 6003 RValue<Int4> Insert(RValue<Int4> x, RValue<Int> element, int i) 6004 { 6005 return RValue<Int4>(Nucleus::createInsertElement(x.value, element.value, i)); 6006 } 6007 6008 RValue<Int> SignMask(RValue<Int4> x) 6009 { 6010 if(emulateIntrinsics || CPUID::ARM) 6011 { 6012 Int4 xx = (x >> 31) & Int4(0x00000001, 0x00000002, 0x00000004, 0x00000008); 6013 return Extract(xx, 0) | Extract(xx, 1) | Extract(xx, 2) | Extract(xx, 3); 6014 } 6015 else 6016 { 6017 Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); 6018 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 6019 auto target = ::context->getConstantUndef(Ice::IceType_i32); 6020 auto movmsk = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 6021 movmsk->addArg(x.value); 6022 ::basicBlock->appendInst(movmsk); 6023 6024 return RValue<Int>(V(result)); 6025 } 6026 } 6027 6028 RValue<Int4> Swizzle(RValue<Int4> x, unsigned char select) 6029 { 6030 return RValue<Int4>(createSwizzle4(x.value, select)); 6031 } 6032 6033 Type *Int4::getType() 6034 { 6035 return T(Ice::IceType_v4i32); 6036 } 6037 6038 UInt4::UInt4() : XYZW(this) 6039 { 6040 } 6041 6042 UInt4::UInt4(RValue<Float4> cast) : XYZW(this) 6043 { 6044 // Smallest positive value representable in UInt, but not in Int 6045 const unsigned int ustart = 0x80000000u; 6046 const float ustartf = float(ustart); 6047 6048 // Check if the value can be represented as an Int 6049 Int4 uiValue = CmpNLT(cast, Float4(ustartf)); 6050 // If the value is too large, subtract ustart and re-add it after conversion. 6051 uiValue = (uiValue & As<Int4>(As<UInt4>(Int4(cast - Float4(ustartf))) + UInt4(ustart))) | 6052 // Otherwise, just convert normally 6053 (~uiValue & Int4(cast)); 6054 // If the value is negative, store 0, otherwise store the result of the conversion 6055 storeValue((~(As<Int4>(cast) >> 31) & uiValue).value); 6056 } 6057 6058 UInt4::UInt4(int xyzw) : XYZW(this) 6059 { 6060 constant(xyzw, xyzw, xyzw, xyzw); 6061 } 6062 6063 UInt4::UInt4(int x, int yzw) : XYZW(this) 6064 { 6065 constant(x, yzw, yzw, yzw); 6066 } 6067 6068 UInt4::UInt4(int x, int y, int zw) : XYZW(this) 6069 { 6070 constant(x, y, zw, zw); 6071 } 6072 6073 UInt4::UInt4(int x, int y, int z, int w) : XYZW(this) 6074 { 6075 constant(x, y, z, w); 6076 } 6077 6078 void UInt4::constant(int x, int y, int z, int w) 6079 { 6080 int64_t constantVector[4] = {x, y, z, w}; 6081 storeValue(Nucleus::createConstantVector(constantVector, getType())); 6082 } 6083 6084 UInt4::UInt4(RValue<UInt4> rhs) : XYZW(this) 6085 { 6086 storeValue(rhs.value); 6087 } 6088 6089 UInt4::UInt4(const UInt4 &rhs) : XYZW(this) 6090 { 6091 Value *value = rhs.loadValue(); 6092 storeValue(value); 6093 } 6094 6095 UInt4::UInt4(const Reference<UInt4> &rhs) : XYZW(this) 6096 { 6097 Value *value = rhs.loadValue(); 6098 storeValue(value); 6099 } 6100 6101 UInt4::UInt4(RValue<Int4> rhs) : XYZW(this) 6102 { 6103 storeValue(rhs.value); 6104 } 6105 6106 UInt4::UInt4(const Int4 &rhs) : XYZW(this) 6107 { 6108 Value *value = rhs.loadValue(); 6109 storeValue(value); 6110 } 6111 6112 UInt4::UInt4(const Reference<Int4> &rhs) : XYZW(this) 6113 { 6114 Value *value = rhs.loadValue(); 6115 storeValue(value); 6116 } 6117 6118 UInt4::UInt4(RValue<UInt2> lo, RValue<UInt2> hi) : XYZW(this) 6119 { 6120 int shuffle[4] = {0, 1, 4, 5}; // Real type is v4i32 6121 Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle); 6122 6123 storeValue(packed); 6124 } 6125 6126 RValue<UInt4> UInt4::operator=(RValue<UInt4> rhs) 6127 { 6128 storeValue(rhs.value); 6129 6130 return rhs; 6131 } 6132 6133 RValue<UInt4> UInt4::operator=(const UInt4 &rhs) 6134 { 6135 Value *value = rhs.loadValue(); 6136 storeValue(value); 6137 6138 return RValue<UInt4>(value); 6139 } 6140 6141 RValue<UInt4> UInt4::operator=(const Reference<UInt4> &rhs) 6142 { 6143 Value *value = rhs.loadValue(); 6144 storeValue(value); 6145 6146 return RValue<UInt4>(value); 6147 } 6148 6149 RValue<UInt4> operator+(RValue<UInt4> lhs, RValue<UInt4> rhs) 6150 { 6151 return RValue<UInt4>(Nucleus::createAdd(lhs.value, rhs.value)); 6152 } 6153 6154 RValue<UInt4> operator-(RValue<UInt4> lhs, RValue<UInt4> rhs) 6155 { 6156 return RValue<UInt4>(Nucleus::createSub(lhs.value, rhs.value)); 6157 } 6158 6159 RValue<UInt4> operator*(RValue<UInt4> lhs, RValue<UInt4> rhs) 6160 { 6161 return RValue<UInt4>(Nucleus::createMul(lhs.value, rhs.value)); 6162 } 6163 6164 RValue<UInt4> operator/(RValue<UInt4> lhs, RValue<UInt4> rhs) 6165 { 6166 return RValue<UInt4>(Nucleus::createUDiv(lhs.value, rhs.value)); 6167 } 6168 6169 RValue<UInt4> operator%(RValue<UInt4> lhs, RValue<UInt4> rhs) 6170 { 6171 return RValue<UInt4>(Nucleus::createURem(lhs.value, rhs.value)); 6172 } 6173 6174 RValue<UInt4> operator&(RValue<UInt4> lhs, RValue<UInt4> rhs) 6175 { 6176 return RValue<UInt4>(Nucleus::createAnd(lhs.value, rhs.value)); 6177 } 6178 6179 RValue<UInt4> operator|(RValue<UInt4> lhs, RValue<UInt4> rhs) 6180 { 6181 return RValue<UInt4>(Nucleus::createOr(lhs.value, rhs.value)); 6182 } 6183 6184 RValue<UInt4> operator^(RValue<UInt4> lhs, RValue<UInt4> rhs) 6185 { 6186 return RValue<UInt4>(Nucleus::createXor(lhs.value, rhs.value)); 6187 } 6188 6189 RValue<UInt> Extract(RValue<UInt4> x, int i) 6190 { 6191 return RValue<UInt>(Nucleus::createExtractElement(x.value, UInt::getType(), i)); 6192 } 6193 6194 RValue<UInt4> Insert(RValue<UInt4> x, RValue<UInt> element, int i) 6195 { 6196 return RValue<UInt4>(Nucleus::createInsertElement(x.value, element.value, i)); 6197 } 6198 6199 RValue<UInt4> operator<<(RValue<UInt4> lhs, unsigned char rhs) 6200 { 6201 if(emulateIntrinsics) 6202 { 6203 UInt4 result; 6204 result = Insert(result, Extract(lhs, 0) << UInt(rhs), 0); 6205 result = Insert(result, Extract(lhs, 1) << UInt(rhs), 1); 6206 result = Insert(result, Extract(lhs, 2) << UInt(rhs), 2); 6207 result = Insert(result, Extract(lhs, 3) << UInt(rhs), 3); 6208 6209 return result; 6210 } 6211 else 6212 { 6213 return RValue<UInt4>(Nucleus::createShl(lhs.value, V(::context->getConstantInt32(rhs)))); 6214 } 6215 } 6216 6217 RValue<UInt4> operator>>(RValue<UInt4> lhs, unsigned char rhs) 6218 { 6219 if(emulateIntrinsics) 6220 { 6221 UInt4 result; 6222 result = Insert(result, Extract(lhs, 0) >> UInt(rhs), 0); 6223 result = Insert(result, Extract(lhs, 1) >> UInt(rhs), 1); 6224 result = Insert(result, Extract(lhs, 2) >> UInt(rhs), 2); 6225 result = Insert(result, Extract(lhs, 3) >> UInt(rhs), 3); 6226 6227 return result; 6228 } 6229 else 6230 { 6231 return RValue<UInt4>(Nucleus::createLShr(lhs.value, V(::context->getConstantInt32(rhs)))); 6232 } 6233 } 6234 6235 RValue<UInt4> operator<<(RValue<UInt4> lhs, RValue<UInt4> rhs) 6236 { 6237 return RValue<UInt4>(Nucleus::createShl(lhs.value, rhs.value)); 6238 } 6239 6240 RValue<UInt4> operator>>(RValue<UInt4> lhs, RValue<UInt4> rhs) 6241 { 6242 return RValue<UInt4>(Nucleus::createLShr(lhs.value, rhs.value)); 6243 } 6244 6245 RValue<UInt4> operator+=(UInt4 &lhs, RValue<UInt4> rhs) 6246 { 6247 return lhs = lhs + rhs; 6248 } 6249 6250 RValue<UInt4> operator-=(UInt4 &lhs, RValue<UInt4> rhs) 6251 { 6252 return lhs = lhs - rhs; 6253 } 6254 6255 RValue<UInt4> operator*=(UInt4 &lhs, RValue<UInt4> rhs) 6256 { 6257 return lhs = lhs * rhs; 6258 } 6259 6260 // RValue<UInt4> operator/=(UInt4 &lhs, RValue<UInt4> rhs) 6261 // { 6262 // return lhs = lhs / rhs; 6263 // } 6264 6265 // RValue<UInt4> operator%=(UInt4 &lhs, RValue<UInt4> rhs) 6266 // { 6267 // return lhs = lhs % rhs; 6268 // } 6269 6270 RValue<UInt4> operator&=(UInt4 &lhs, RValue<UInt4> rhs) 6271 { 6272 return lhs = lhs & rhs; 6273 } 6274 6275 RValue<UInt4> operator|=(UInt4 &lhs, RValue<UInt4> rhs) 6276 { 6277 return lhs = lhs | rhs; 6278 } 6279 6280 RValue<UInt4> operator^=(UInt4 &lhs, RValue<UInt4> rhs) 6281 { 6282 return lhs = lhs ^ rhs; 6283 } 6284 6285 RValue<UInt4> operator<<=(UInt4 &lhs, unsigned char rhs) 6286 { 6287 return lhs = lhs << rhs; 6288 } 6289 6290 RValue<UInt4> operator>>=(UInt4 &lhs, unsigned char rhs) 6291 { 6292 return lhs = lhs >> rhs; 6293 } 6294 6295 RValue<UInt4> operator+(RValue<UInt4> val) 6296 { 6297 return val; 6298 } 6299 6300 RValue<UInt4> operator-(RValue<UInt4> val) 6301 { 6302 return RValue<UInt4>(Nucleus::createNeg(val.value)); 6303 } 6304 6305 RValue<UInt4> operator~(RValue<UInt4> val) 6306 { 6307 return RValue<UInt4>(Nucleus::createNot(val.value)); 6308 } 6309 6310 RValue<UInt4> CmpEQ(RValue<UInt4> x, RValue<UInt4> y) 6311 { 6312 return RValue<UInt4>(Nucleus::createICmpEQ(x.value, y.value)); 6313 } 6314 6315 RValue<UInt4> CmpLT(RValue<UInt4> x, RValue<UInt4> y) 6316 { 6317 return RValue<UInt4>(Nucleus::createICmpULT(x.value, y.value)); 6318 } 6319 6320 RValue<UInt4> CmpLE(RValue<UInt4> x, RValue<UInt4> y) 6321 { 6322 return RValue<UInt4>(Nucleus::createICmpULE(x.value, y.value)); 6323 } 6324 6325 RValue<UInt4> CmpNEQ(RValue<UInt4> x, RValue<UInt4> y) 6326 { 6327 return RValue<UInt4>(Nucleus::createICmpNE(x.value, y.value)); 6328 } 6329 6330 RValue<UInt4> CmpNLT(RValue<UInt4> x, RValue<UInt4> y) 6331 { 6332 return RValue<UInt4>(Nucleus::createICmpUGE(x.value, y.value)); 6333 } 6334 6335 RValue<UInt4> CmpNLE(RValue<UInt4> x, RValue<UInt4> y) 6336 { 6337 return RValue<UInt4>(Nucleus::createICmpUGT(x.value, y.value)); 6338 } 6339 6340 RValue<UInt4> Max(RValue<UInt4> x, RValue<UInt4> y) 6341 { 6342 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 6343 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value, y.value); 6344 ::basicBlock->appendInst(cmp); 6345 6346 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); 6347 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 6348 ::basicBlock->appendInst(select); 6349 6350 return RValue<UInt4>(V(result)); 6351 } 6352 6353 RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y) 6354 { 6355 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 6356 auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value, y.value); 6357 ::basicBlock->appendInst(cmp); 6358 6359 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); 6360 auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value); 6361 ::basicBlock->appendInst(select); 6362 6363 return RValue<UInt4>(V(result)); 6364 } 6365 6366 Type *UInt4::getType() 6367 { 6368 return T(Ice::IceType_v4i32); 6369 } 6370 6371 Float::Float(RValue<Int> cast) 6372 { 6373 Value *integer = Nucleus::createSIToFP(cast.value, Float::getType()); 6374 6375 storeValue(integer); 6376 } 6377 6378 Float::Float(RValue<UInt> cast) 6379 { 6380 RValue<Float> result = Float(Int(cast & UInt(0x7FFFFFFF))) + 6381 As<Float>((As<Int>(cast) >> 31) & As<Int>(Float(0x80000000u))); 6382 6383 storeValue(result.value); 6384 } 6385 6386 Float::Float(float x) 6387 { 6388 storeValue(Nucleus::createConstantFloat(x)); 6389 } 6390 6391 Float::Float(RValue<Float> rhs) 6392 { 6393 storeValue(rhs.value); 6394 } 6395 6396 Float::Float(const Float &rhs) 6397 { 6398 Value *value = rhs.loadValue(); 6399 storeValue(value); 6400 } 6401 6402 Float::Float(const Reference<Float> &rhs) 6403 { 6404 Value *value = rhs.loadValue(); 6405 storeValue(value); 6406 } 6407 6408 RValue<Float> Float::operator=(RValue<Float> rhs) 6409 { 6410 storeValue(rhs.value); 6411 6412 return rhs; 6413 } 6414 6415 RValue<Float> Float::operator=(const Float &rhs) 6416 { 6417 Value *value = rhs.loadValue(); 6418 storeValue(value); 6419 6420 return RValue<Float>(value); 6421 } 6422 6423 RValue<Float> Float::operator=(const Reference<Float> &rhs) 6424 { 6425 Value *value = rhs.loadValue(); 6426 storeValue(value); 6427 6428 return RValue<Float>(value); 6429 } 6430 6431 RValue<Float> operator+(RValue<Float> lhs, RValue<Float> rhs) 6432 { 6433 return RValue<Float>(Nucleus::createFAdd(lhs.value, rhs.value)); 6434 } 6435 6436 RValue<Float> operator-(RValue<Float> lhs, RValue<Float> rhs) 6437 { 6438 return RValue<Float>(Nucleus::createFSub(lhs.value, rhs.value)); 6439 } 6440 6441 RValue<Float> operator*(RValue<Float> lhs, RValue<Float> rhs) 6442 { 6443 return RValue<Float>(Nucleus::createFMul(lhs.value, rhs.value)); 6444 } 6445 6446 RValue<Float> operator/(RValue<Float> lhs, RValue<Float> rhs) 6447 { 6448 return RValue<Float>(Nucleus::createFDiv(lhs.value, rhs.value)); 6449 } 6450 6451 RValue<Float> operator+=(Float &lhs, RValue<Float> rhs) 6452 { 6453 return lhs = lhs + rhs; 6454 } 6455 6456 RValue<Float> operator-=(Float &lhs, RValue<Float> rhs) 6457 { 6458 return lhs = lhs - rhs; 6459 } 6460 6461 RValue<Float> operator*=(Float &lhs, RValue<Float> rhs) 6462 { 6463 return lhs = lhs * rhs; 6464 } 6465 6466 RValue<Float> operator/=(Float &lhs, RValue<Float> rhs) 6467 { 6468 return lhs = lhs / rhs; 6469 } 6470 6471 RValue<Float> operator+(RValue<Float> val) 6472 { 6473 return val; 6474 } 6475 6476 RValue<Float> operator-(RValue<Float> val) 6477 { 6478 return RValue<Float>(Nucleus::createFNeg(val.value)); 6479 } 6480 6481 RValue<Bool> operator<(RValue<Float> lhs, RValue<Float> rhs) 6482 { 6483 return RValue<Bool>(Nucleus::createFCmpOLT(lhs.value, rhs.value)); 6484 } 6485 6486 RValue<Bool> operator<=(RValue<Float> lhs, RValue<Float> rhs) 6487 { 6488 return RValue<Bool>(Nucleus::createFCmpOLE(lhs.value, rhs.value)); 6489 } 6490 6491 RValue<Bool> operator>(RValue<Float> lhs, RValue<Float> rhs) 6492 { 6493 return RValue<Bool>(Nucleus::createFCmpOGT(lhs.value, rhs.value)); 6494 } 6495 6496 RValue<Bool> operator>=(RValue<Float> lhs, RValue<Float> rhs) 6497 { 6498 return RValue<Bool>(Nucleus::createFCmpOGE(lhs.value, rhs.value)); 6499 } 6500 6501 RValue<Bool> operator!=(RValue<Float> lhs, RValue<Float> rhs) 6502 { 6503 return RValue<Bool>(Nucleus::createFCmpONE(lhs.value, rhs.value)); 6504 } 6505 6506 RValue<Bool> operator==(RValue<Float> lhs, RValue<Float> rhs) 6507 { 6508 return RValue<Bool>(Nucleus::createFCmpOEQ(lhs.value, rhs.value)); 6509 } 6510 6511 RValue<Float> Abs(RValue<Float> x) 6512 { 6513 return IfThenElse(x > 0.0f, x, -x); 6514 } 6515 6516 RValue<Float> Max(RValue<Float> x, RValue<Float> y) 6517 { 6518 return IfThenElse(x > y, x, y); 6519 } 6520 6521 RValue<Float> Min(RValue<Float> x, RValue<Float> y) 6522 { 6523 return IfThenElse(x < y, x, y); 6524 } 6525 6526 RValue<Float> Rcp_pp(RValue<Float> x, bool exactAtPow2) 6527 { 6528 return 1.0f / x; 6529 } 6530 6531 RValue<Float> RcpSqrt_pp(RValue<Float> x) 6532 { 6533 return Rcp_pp(Sqrt(x)); 6534 } 6535 6536 RValue<Float> Sqrt(RValue<Float> x) 6537 { 6538 Ice::Variable *result = ::function->makeVariable(Ice::IceType_f32); 6539 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Sqrt, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 6540 auto target = ::context->getConstantUndef(Ice::IceType_i32); 6541 auto sqrt = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 6542 sqrt->addArg(x.value); 6543 ::basicBlock->appendInst(sqrt); 6544 6545 return RValue<Float>(V(result)); 6546 } 6547 6548 RValue<Float> Round(RValue<Float> x) 6549 { 6550 return Float4(Round(Float4(x))).x; 6551 } 6552 6553 RValue<Float> Trunc(RValue<Float> x) 6554 { 6555 return Float4(Trunc(Float4(x))).x; 6556 } 6557 6558 RValue<Float> Frac(RValue<Float> x) 6559 { 6560 return Float4(Frac(Float4(x))).x; 6561 } 6562 6563 RValue<Float> Floor(RValue<Float> x) 6564 { 6565 return Float4(Floor(Float4(x))).x; 6566 } 6567 6568 RValue<Float> Ceil(RValue<Float> x) 6569 { 6570 return Float4(Ceil(Float4(x))).x; 6571 } 6572 6573 Type *Float::getType() 6574 { 6575 return T(Ice::IceType_f32); 6576 } 6577 6578 Float2::Float2(RValue<Float4> cast) 6579 { 6580 storeValue(Nucleus::createBitCast(cast.value, getType())); 6581 } 6582 6583 Type *Float2::getType() 6584 { 6585 return T(Type_v2f32); 6586 } 6587 6588 Float4::Float4(RValue<Byte4> cast) : XYZW(this) 6589 { 6590 Value *a = Int4(cast).loadValue(); 6591 Value *xyzw = Nucleus::createSIToFP(a, Float4::getType()); 6592 6593 storeValue(xyzw); 6594 } 6595 6596 Float4::Float4(RValue<SByte4> cast) : XYZW(this) 6597 { 6598 Value *a = Int4(cast).loadValue(); 6599 Value *xyzw = Nucleus::createSIToFP(a, Float4::getType()); 6600 6601 storeValue(xyzw); 6602 } 6603 6604 Float4::Float4(RValue<Short4> cast) : XYZW(this) 6605 { 6606 Int4 c(cast); 6607 storeValue(Nucleus::createSIToFP(RValue<Int4>(c).value, Float4::getType())); 6608 } 6609 6610 Float4::Float4(RValue<UShort4> cast) : XYZW(this) 6611 { 6612 Int4 c(cast); 6613 storeValue(Nucleus::createSIToFP(RValue<Int4>(c).value, Float4::getType())); 6614 } 6615 6616 Float4::Float4(RValue<Int4> cast) : XYZW(this) 6617 { 6618 Value *xyzw = Nucleus::createSIToFP(cast.value, Float4::getType()); 6619 6620 storeValue(xyzw); 6621 } 6622 6623 Float4::Float4(RValue<UInt4> cast) : XYZW(this) 6624 { 6625 RValue<Float4> result = Float4(Int4(cast & UInt4(0x7FFFFFFF))) + 6626 As<Float4>((As<Int4>(cast) >> 31) & As<Int4>(Float4(0x80000000u))); 6627 6628 storeValue(result.value); 6629 } 6630 6631 Float4::Float4() : XYZW(this) 6632 { 6633 } 6634 6635 Float4::Float4(float xyzw) : XYZW(this) 6636 { 6637 constant(xyzw, xyzw, xyzw, xyzw); 6638 } 6639 6640 Float4::Float4(float x, float yzw) : XYZW(this) 6641 { 6642 constant(x, yzw, yzw, yzw); 6643 } 6644 6645 Float4::Float4(float x, float y, float zw) : XYZW(this) 6646 { 6647 constant(x, y, zw, zw); 6648 } 6649 6650 Float4::Float4(float x, float y, float z, float w) : XYZW(this) 6651 { 6652 constant(x, y, z, w); 6653 } 6654 6655 void Float4::constant(float x, float y, float z, float w) 6656 { 6657 double constantVector[4] = {x, y, z, w}; 6658 storeValue(Nucleus::createConstantVector(constantVector, getType())); 6659 } 6660 6661 Float4::Float4(RValue<Float4> rhs) : XYZW(this) 6662 { 6663 storeValue(rhs.value); 6664 } 6665 6666 Float4::Float4(const Float4 &rhs) : XYZW(this) 6667 { 6668 Value *value = rhs.loadValue(); 6669 storeValue(value); 6670 } 6671 6672 Float4::Float4(const Reference<Float4> &rhs) : XYZW(this) 6673 { 6674 Value *value = rhs.loadValue(); 6675 storeValue(value); 6676 } 6677 6678 Float4::Float4(RValue<Float> rhs) : XYZW(this) 6679 { 6680 Value *vector = Nucleus::createBitCast(rhs.value, Float4::getType()); 6681 6682 int swizzle[4] = {0, 0, 0, 0}; 6683 Value *replicate = Nucleus::createShuffleVector(vector, vector, swizzle); 6684 6685 storeValue(replicate); 6686 } 6687 6688 Float4::Float4(const Float &rhs) : XYZW(this) 6689 { 6690 *this = RValue<Float>(rhs.loadValue()); 6691 } 6692 6693 Float4::Float4(const Reference<Float> &rhs) : XYZW(this) 6694 { 6695 *this = RValue<Float>(rhs.loadValue()); 6696 } 6697 6698 RValue<Float4> Float4::operator=(float x) 6699 { 6700 return *this = Float4(x, x, x, x); 6701 } 6702 6703 RValue<Float4> Float4::operator=(RValue<Float4> rhs) 6704 { 6705 storeValue(rhs.value); 6706 6707 return rhs; 6708 } 6709 6710 RValue<Float4> Float4::operator=(const Float4 &rhs) 6711 { 6712 Value *value = rhs.loadValue(); 6713 storeValue(value); 6714 6715 return RValue<Float4>(value); 6716 } 6717 6718 RValue<Float4> Float4::operator=(const Reference<Float4> &rhs) 6719 { 6720 Value *value = rhs.loadValue(); 6721 storeValue(value); 6722 6723 return RValue<Float4>(value); 6724 } 6725 6726 RValue<Float4> Float4::operator=(RValue<Float> rhs) 6727 { 6728 return *this = Float4(rhs); 6729 } 6730 6731 RValue<Float4> Float4::operator=(const Float &rhs) 6732 { 6733 return *this = Float4(rhs); 6734 } 6735 6736 RValue<Float4> Float4::operator=(const Reference<Float> &rhs) 6737 { 6738 return *this = Float4(rhs); 6739 } 6740 6741 RValue<Float4> operator+(RValue<Float4> lhs, RValue<Float4> rhs) 6742 { 6743 return RValue<Float4>(Nucleus::createFAdd(lhs.value, rhs.value)); 6744 } 6745 6746 RValue<Float4> operator-(RValue<Float4> lhs, RValue<Float4> rhs) 6747 { 6748 return RValue<Float4>(Nucleus::createFSub(lhs.value, rhs.value)); 6749 } 6750 6751 RValue<Float4> operator*(RValue<Float4> lhs, RValue<Float4> rhs) 6752 { 6753 return RValue<Float4>(Nucleus::createFMul(lhs.value, rhs.value)); 6754 } 6755 6756 RValue<Float4> operator/(RValue<Float4> lhs, RValue<Float4> rhs) 6757 { 6758 return RValue<Float4>(Nucleus::createFDiv(lhs.value, rhs.value)); 6759 } 6760 6761 RValue<Float4> operator%(RValue<Float4> lhs, RValue<Float4> rhs) 6762 { 6763 return RValue<Float4>(Nucleus::createFRem(lhs.value, rhs.value)); 6764 } 6765 6766 RValue<Float4> operator+=(Float4 &lhs, RValue<Float4> rhs) 6767 { 6768 return lhs = lhs + rhs; 6769 } 6770 6771 RValue<Float4> operator-=(Float4 &lhs, RValue<Float4> rhs) 6772 { 6773 return lhs = lhs - rhs; 6774 } 6775 6776 RValue<Float4> operator*=(Float4 &lhs, RValue<Float4> rhs) 6777 { 6778 return lhs = lhs * rhs; 6779 } 6780 6781 RValue<Float4> operator/=(Float4 &lhs, RValue<Float4> rhs) 6782 { 6783 return lhs = lhs / rhs; 6784 } 6785 6786 RValue<Float4> operator%=(Float4 &lhs, RValue<Float4> rhs) 6787 { 6788 return lhs = lhs % rhs; 6789 } 6790 6791 RValue<Float4> operator+(RValue<Float4> val) 6792 { 6793 return val; 6794 } 6795 6796 RValue<Float4> operator-(RValue<Float4> val) 6797 { 6798 return RValue<Float4>(Nucleus::createFNeg(val.value)); 6799 } 6800 6801 RValue<Float4> Abs(RValue<Float4> x) 6802 { 6803 Value *vector = Nucleus::createBitCast(x.value, Int4::getType()); 6804 int64_t constantVector[4] = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; 6805 Value *result = Nucleus::createAnd(vector, V(Nucleus::createConstantVector(constantVector, Int4::getType()))); 6806 6807 return As<Float4>(result); 6808 } 6809 6810 RValue<Float4> Max(RValue<Float4> x, RValue<Float4> y) 6811 { 6812 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 6813 auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Ogt, condition, x.value, y.value); 6814 ::basicBlock->appendInst(cmp); 6815 6816 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 6817 auto select = Ice::InstSelect::create(::function, result, condition, x.value, y.value); 6818 ::basicBlock->appendInst(select); 6819 6820 return RValue<Float4>(V(result)); 6821 } 6822 6823 RValue<Float4> Min(RValue<Float4> x, RValue<Float4> y) 6824 { 6825 Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1); 6826 auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Olt, condition, x.value, y.value); 6827 ::basicBlock->appendInst(cmp); 6828 6829 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 6830 auto select = Ice::InstSelect::create(::function, result, condition, x.value, y.value); 6831 ::basicBlock->appendInst(select); 6832 6833 return RValue<Float4>(V(result)); 6834 } 6835 6836 RValue<Float4> Rcp_pp(RValue<Float4> x, bool exactAtPow2) 6837 { 6838 return Float4(1.0f) / x; 6839 } 6840 6841 RValue<Float4> RcpSqrt_pp(RValue<Float4> x) 6842 { 6843 return Rcp_pp(Sqrt(x)); 6844 } 6845 6846 RValue<Float4> Sqrt(RValue<Float4> x) 6847 { 6848 if(emulateIntrinsics || CPUID::ARM) 6849 { 6850 Float4 result; 6851 result.x = Sqrt(Float(Float4(x).x)); 6852 result.y = Sqrt(Float(Float4(x).y)); 6853 result.z = Sqrt(Float(Float4(x).z)); 6854 result.w = Sqrt(Float(Float4(x).w)); 6855 6856 return result; 6857 } 6858 else 6859 { 6860 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 6861 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Sqrt, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 6862 auto target = ::context->getConstantUndef(Ice::IceType_i32); 6863 auto sqrt = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 6864 sqrt->addArg(x.value); 6865 ::basicBlock->appendInst(sqrt); 6866 6867 return RValue<Float4>(V(result)); 6868 } 6869 } 6870 6871 RValue<Float4> Insert(RValue<Float4> x, RValue<Float> element, int i) 6872 { 6873 return RValue<Float4>(Nucleus::createInsertElement(x.value, element.value, i)); 6874 } 6875 6876 RValue<Float> Extract(RValue<Float4> x, int i) 6877 { 6878 return RValue<Float>(Nucleus::createExtractElement(x.value, Float::getType(), i)); 6879 } 6880 6881 RValue<Float4> Swizzle(RValue<Float4> x, unsigned char select) 6882 { 6883 return RValue<Float4>(createSwizzle4(x.value, select)); 6884 } 6885 6886 RValue<Float4> ShuffleLowHigh(RValue<Float4> x, RValue<Float4> y, unsigned char imm) 6887 { 6888 int shuffle[4] = 6889 { 6890 ((imm >> 0) & 0x03) + 0, 6891 ((imm >> 2) & 0x03) + 0, 6892 ((imm >> 4) & 0x03) + 4, 6893 ((imm >> 6) & 0x03) + 4, 6894 }; 6895 6896 return RValue<Float4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 6897 } 6898 6899 RValue<Float4> UnpackLow(RValue<Float4> x, RValue<Float4> y) 6900 { 6901 int shuffle[4] = {0, 4, 1, 5}; 6902 return RValue<Float4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 6903 } 6904 6905 RValue<Float4> UnpackHigh(RValue<Float4> x, RValue<Float4> y) 6906 { 6907 int shuffle[4] = {2, 6, 3, 7}; 6908 return RValue<Float4>(Nucleus::createShuffleVector(x.value, y.value, shuffle)); 6909 } 6910 6911 RValue<Float4> Mask(Float4 &lhs, RValue<Float4> rhs, unsigned char select) 6912 { 6913 Value *vector = lhs.loadValue(); 6914 Value *result = createMask4(vector, rhs.value, select); 6915 lhs.storeValue(result); 6916 6917 return RValue<Float4>(result); 6918 } 6919 6920 RValue<Int> SignMask(RValue<Float4> x) 6921 { 6922 if(emulateIntrinsics || CPUID::ARM) 6923 { 6924 Int4 xx = (As<Int4>(x) >> 31) & Int4(0x00000001, 0x00000002, 0x00000004, 0x00000008); 6925 return Extract(xx, 0) | Extract(xx, 1) | Extract(xx, 2) | Extract(xx, 3); 6926 } 6927 else 6928 { 6929 Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); 6930 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::SignMask, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 6931 auto target = ::context->getConstantUndef(Ice::IceType_i32); 6932 auto movmsk = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic); 6933 movmsk->addArg(x.value); 6934 ::basicBlock->appendInst(movmsk); 6935 6936 return RValue<Int>(V(result)); 6937 } 6938 } 6939 6940 RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y) 6941 { 6942 return RValue<Int4>(Nucleus::createFCmpOEQ(x.value, y.value)); 6943 } 6944 6945 RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y) 6946 { 6947 return RValue<Int4>(Nucleus::createFCmpOLT(x.value, y.value)); 6948 } 6949 6950 RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y) 6951 { 6952 return RValue<Int4>(Nucleus::createFCmpOLE(x.value, y.value)); 6953 } 6954 6955 RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y) 6956 { 6957 return RValue<Int4>(Nucleus::createFCmpONE(x.value, y.value)); 6958 } 6959 6960 RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y) 6961 { 6962 return RValue<Int4>(Nucleus::createFCmpOGE(x.value, y.value)); 6963 } 6964 6965 RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y) 6966 { 6967 return RValue<Int4>(Nucleus::createFCmpOGT(x.value, y.value)); 6968 } 6969 6970 RValue<Int4> IsInf(RValue<Float4> x) 6971 { 6972 return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000)); 6973 } 6974 6975 RValue<Int4> IsNan(RValue<Float4> x) 6976 { 6977 return ~CmpEQ(x, x); 6978 } 6979 6980 RValue<Float4> Round(RValue<Float4> x) 6981 { 6982 if(emulateIntrinsics || CPUID::ARM) 6983 { 6984 // Push the fractional part off the mantissa. Accurate up to +/-2^22. 6985 return (x + Float4(0x00C00000)) - Float4(0x00C00000); 6986 } 6987 else if(CPUID::SSE4_1) 6988 { 6989 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 6990 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 6991 auto target = ::context->getConstantUndef(Ice::IceType_i32); 6992 auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 6993 round->addArg(x.value); 6994 round->addArg(::context->getConstantInt32(0)); 6995 ::basicBlock->appendInst(round); 6996 6997 return RValue<Float4>(V(result)); 6998 } 6999 else 7000 { 7001 return Float4(RoundInt(x)); 7002 } 7003 } 7004 7005 RValue<Float4> Trunc(RValue<Float4> x) 7006 { 7007 if(CPUID::SSE4_1) 7008 { 7009 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 7010 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 7011 auto target = ::context->getConstantUndef(Ice::IceType_i32); 7012 auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 7013 round->addArg(x.value); 7014 round->addArg(::context->getConstantInt32(3)); 7015 ::basicBlock->appendInst(round); 7016 7017 return RValue<Float4>(V(result)); 7018 } 7019 else 7020 { 7021 return Float4(Int4(x)); 7022 } 7023 } 7024 7025 RValue<Float4> Frac(RValue<Float4> x) 7026 { 7027 Float4 frc; 7028 7029 if(CPUID::SSE4_1) 7030 { 7031 frc = x - Floor(x); 7032 } 7033 else 7034 { 7035 frc = x - Float4(Int4(x)); // Signed fractional part. 7036 7037 frc += As<Float4>(As<Int4>(CmpNLE(Float4(0.0f), frc)) & As<Int4>(Float4(1, 1, 1, 1))); // Add 1.0 if negative. 7038 } 7039 7040 // x - floor(x) can be 1.0 for very small negative x. 7041 // Clamp against the value just below 1.0. 7042 return Min(frc, As<Float4>(Int4(0x3F7FFFFF))); 7043 } 7044 7045 RValue<Float4> Floor(RValue<Float4> x) 7046 { 7047 if(CPUID::SSE4_1) 7048 { 7049 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 7050 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 7051 auto target = ::context->getConstantUndef(Ice::IceType_i32); 7052 auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 7053 round->addArg(x.value); 7054 round->addArg(::context->getConstantInt32(1)); 7055 ::basicBlock->appendInst(round); 7056 7057 return RValue<Float4>(V(result)); 7058 } 7059 else 7060 { 7061 return x - Frac(x); 7062 } 7063 } 7064 7065 RValue<Float4> Ceil(RValue<Float4> x) 7066 { 7067 if(CPUID::SSE4_1) 7068 { 7069 Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); 7070 const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; 7071 auto target = ::context->getConstantUndef(Ice::IceType_i32); 7072 auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); 7073 round->addArg(x.value); 7074 round->addArg(::context->getConstantInt32(2)); 7075 ::basicBlock->appendInst(round); 7076 7077 return RValue<Float4>(V(result)); 7078 } 7079 else 7080 { 7081 return -Floor(-x); 7082 } 7083 } 7084 7085 Type *Float4::getType() 7086 { 7087 return T(Ice::IceType_v4f32); 7088 } 7089 7090 RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, int offset) 7091 { 7092 return lhs + RValue<Int>(Nucleus::createConstantInt(offset)); 7093 } 7094 7095 RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<Int> offset) 7096 { 7097 return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, false)); 7098 } 7099 7100 RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<UInt> offset) 7101 { 7102 return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, true)); 7103 } 7104 7105 RValue<Pointer<Byte>> operator+=(Pointer<Byte> &lhs, int offset) 7106 { 7107 return lhs = lhs + offset; 7108 } 7109 7110 RValue<Pointer<Byte>> operator+=(Pointer<Byte> &lhs, RValue<Int> offset) 7111 { 7112 return lhs = lhs + offset; 7113 } 7114 7115 RValue<Pointer<Byte>> operator+=(Pointer<Byte> &lhs, RValue<UInt> offset) 7116 { 7117 return lhs = lhs + offset; 7118 } 7119 7120 RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, int offset) 7121 { 7122 return lhs + -offset; 7123 } 7124 7125 RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<Int> offset) 7126 { 7127 return lhs + -offset; 7128 } 7129 7130 RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<UInt> offset) 7131 { 7132 return lhs + -offset; 7133 } 7134 7135 RValue<Pointer<Byte>> operator-=(Pointer<Byte> &lhs, int offset) 7136 { 7137 return lhs = lhs - offset; 7138 } 7139 7140 RValue<Pointer<Byte>> operator-=(Pointer<Byte> &lhs, RValue<Int> offset) 7141 { 7142 return lhs = lhs - offset; 7143 } 7144 7145 RValue<Pointer<Byte>> operator-=(Pointer<Byte> &lhs, RValue<UInt> offset) 7146 { 7147 return lhs = lhs - offset; 7148 } 7149 7150 void Return() 7151 { 7152 Nucleus::createRetVoid(); 7153 Nucleus::setInsertBlock(Nucleus::createBasicBlock()); 7154 Nucleus::createUnreachable(); 7155 } 7156 7157 void Return(RValue<Int> ret) 7158 { 7159 Nucleus::createRet(ret.value); 7160 Nucleus::setInsertBlock(Nucleus::createBasicBlock()); 7161 Nucleus::createUnreachable(); 7162 } 7163 7164 void branch(RValue<Bool> cmp, BasicBlock *bodyBB, BasicBlock *endBB) 7165 { 7166 Nucleus::createCondBr(cmp.value, bodyBB, endBB); 7167 Nucleus::setInsertBlock(bodyBB); 7168 } 7169 7170 RValue<Long> Ticks() 7171 { 7172 assert(false && "UNIMPLEMENTED"); return RValue<Long>(V(nullptr)); 7173 } 7174 } 7175