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
50namespace
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
64namespace
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
126namespace 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 &sectionHeader(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