diff options
Diffstat (limited to 'ARMeilleure/CodeGen/X86')
| -rw-r--r-- | ARMeilleure/CodeGen/X86/Assembler.cs | 141 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/X86/CodeGenerator.cs | 72 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/X86/PreAllocator.cs | 395 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/X86/X86Optimizer.cs | 71 |
4 files changed, 326 insertions, 353 deletions
diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs index 39aeb7c9..044f6047 100644 --- a/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/ARMeilleure/CodeGen/X86/Assembler.cs @@ -329,12 +329,12 @@ namespace ARMeilleure.CodeGen.X86 public void Bswap(Operand dest) { - WriteInstruction(dest, null, dest.Type, X86Instruction.Bswap); + WriteInstruction(dest, default, dest.Type, X86Instruction.Bswap); } public void Call(Operand dest) { - WriteInstruction(dest, null, OperandType.None, X86Instruction.Call); + WriteInstruction(dest, default, OperandType.None, X86Instruction.Call); } public void Cdq() @@ -346,7 +346,7 @@ namespace ARMeilleure.CodeGen.X86 { InstructionInfo info = _instTable[(int)X86Instruction.Cmovcc]; - WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM | (int)condition, rrm: true); + WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM | (int)condition, rrm: true); } public void Cmp(Operand src1, Operand src2, OperandType type) @@ -360,30 +360,38 @@ namespace ARMeilleure.CodeGen.X86 WriteByte(0x99); } - public void Cmpxchg(MemoryOperand memOp, Operand src) + public void Cmpxchg(Operand memOp, Operand src) { + Debug.Assert(memOp.Kind == OperandKind.Memory); + WriteByte(LockPrefix); WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg); } - public void Cmpxchg16(MemoryOperand memOp, Operand src) + public void Cmpxchg16(Operand memOp, Operand src) { + Debug.Assert(memOp.Kind == OperandKind.Memory); + WriteByte(LockPrefix); WriteByte(0x66); WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg); } - public void Cmpxchg16b(MemoryOperand memOp) + public void Cmpxchg16b(Operand memOp) { + Debug.Assert(memOp.Kind == OperandKind.Memory); + WriteByte(LockPrefix); - WriteInstruction(memOp, null, OperandType.None, X86Instruction.Cmpxchg16b); + WriteInstruction(memOp, default, OperandType.None, X86Instruction.Cmpxchg16b); } - public void Cmpxchg8(MemoryOperand memOp, Operand src) + public void Cmpxchg8(Operand memOp, Operand src) { + Debug.Assert(memOp.Kind == OperandKind.Memory); + WriteByte(LockPrefix); WriteInstruction(memOp, src, src.Type, X86Instruction.Cmpxchg8); @@ -391,12 +399,12 @@ namespace ARMeilleure.CodeGen.X86 public void Comisd(Operand src1, Operand src2) { - WriteInstruction(src1, null, src2, X86Instruction.Comisd); + WriteInstruction(src1, default, src2, X86Instruction.Comisd); } public void Comiss(Operand src1, Operand src2) { - WriteInstruction(src1, null, src2, X86Instruction.Comiss); + WriteInstruction(src1, default, src2, X86Instruction.Comiss); } public void Cvtsd2ss(Operand dest, Operand src1, Operand src2) @@ -421,7 +429,7 @@ namespace ARMeilleure.CodeGen.X86 public void Div(Operand source) { - WriteInstruction(null, source, source.Type, X86Instruction.Div); + WriteInstruction(default, source, source.Type, X86Instruction.Div); } public void Divsd(Operand dest, Operand src1, Operand src2) @@ -436,12 +444,12 @@ namespace ARMeilleure.CodeGen.X86 public void Idiv(Operand source) { - WriteInstruction(null, source, source.Type, X86Instruction.Idiv); + WriteInstruction(default, source, source.Type, X86Instruction.Idiv); } public void Imul(Operand source) { - WriteInstruction(null, source, source.Type, X86Instruction.Imul128); + WriteInstruction(default, source, source.Type, X86Instruction.Imul128); } public void Imul(Operand dest, Operand source, OperandType type) @@ -465,13 +473,13 @@ namespace ARMeilleure.CodeGen.X86 if (IsImm8(src2.Value, src2.Type) && info.OpRMImm8 != BadOp) { - WriteOpCode(dest, null, src1, type, info.Flags, info.OpRMImm8, rrm: true); + WriteOpCode(dest, default, src1, type, info.Flags, info.OpRMImm8, rrm: true); WriteByte(src2.AsByte()); } else if (IsImm32(src2.Value, src2.Type) && info.OpRMImm32 != BadOp) { - WriteOpCode(dest, null, src1, type, info.Flags, info.OpRMImm32, rrm: true); + WriteOpCode(dest, default, src1, type, info.Flags, info.OpRMImm32, rrm: true); WriteInt32(src2.AsInt32()); } @@ -531,12 +539,12 @@ namespace ARMeilleure.CodeGen.X86 public void Jmp(Operand dest) { - WriteInstruction(dest, null, OperandType.None, X86Instruction.Jmp); + WriteInstruction(dest, default, OperandType.None, X86Instruction.Jmp); } public void Ldmxcsr(Operand dest) { - WriteInstruction(dest, null, OperandType.I32, X86Instruction.Ldmxcsr); + WriteInstruction(dest, default, OperandType.I32, X86Instruction.Ldmxcsr); } public void Lea(Operand dest, Operand source, OperandType type) @@ -565,17 +573,17 @@ namespace ARMeilleure.CodeGen.X86 if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) { - WriteOpCode(dest, null, source, OperandType.None, info.Flags, info.OpRRM, rrm: true); + WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true); } else { - WriteOpCode(dest, null, source, OperandType.None, info.Flags, info.OpRMR); + WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRMR); } } public void Movdqu(Operand dest, Operand source) { - WriteInstruction(dest, null, source, X86Instruction.Movdqu); + WriteInstruction(dest, default, source, X86Instruction.Movdqu); } public void Movhlps(Operand dest, Operand src1, Operand src2) @@ -596,11 +604,11 @@ namespace ARMeilleure.CodeGen.X86 if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) { - WriteOpCode(dest, null, source, OperandType.None, flags, info.OpRRM, rrm: true); + WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true); } else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory) { - WriteOpCode(dest, null, source, OperandType.None, flags, info.OpRMR); + WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR); } else { @@ -645,7 +653,7 @@ namespace ARMeilleure.CodeGen.X86 public void Mul(Operand source) { - WriteInstruction(null, source, source.Type, X86Instruction.Mul128); + WriteInstruction(default, source, source.Type, X86Instruction.Mul128); } public void Mulsd(Operand dest, Operand src1, Operand src2) @@ -660,12 +668,12 @@ namespace ARMeilleure.CodeGen.X86 public void Neg(Operand dest) { - WriteInstruction(dest, null, dest.Type, X86Instruction.Neg); + WriteInstruction(dest, default, dest.Type, X86Instruction.Neg); } public void Not(Operand dest) { - WriteInstruction(dest, null, dest.Type, X86Instruction.Not); + WriteInstruction(dest, default, dest.Type, X86Instruction.Not); } public void Or(Operand dest, Operand source, OperandType type) @@ -675,7 +683,7 @@ namespace ARMeilleure.CodeGen.X86 public void Pclmulqdq(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pclmulqdq); + WriteInstruction(dest, default, source, X86Instruction.Pclmulqdq); WriteByte(imm); } @@ -687,28 +695,28 @@ namespace ARMeilleure.CodeGen.X86 public void Pextrb(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pextrb); + WriteInstruction(dest, default, source, X86Instruction.Pextrb); WriteByte(imm); } public void Pextrd(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pextrd); + WriteInstruction(dest, default, source, X86Instruction.Pextrd); WriteByte(imm); } public void Pextrq(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pextrq); + WriteInstruction(dest, default, source, X86Instruction.Pextrq); WriteByte(imm); } public void Pextrw(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pextrw); + WriteInstruction(dest, default, source, X86Instruction.Pextrw); WriteByte(imm); } @@ -749,7 +757,7 @@ namespace ARMeilleure.CodeGen.X86 } else { - WriteInstruction(dest, null, dest.Type, X86Instruction.Pop); + WriteInstruction(dest, default, dest.Type, X86Instruction.Pop); } } @@ -760,7 +768,7 @@ namespace ARMeilleure.CodeGen.X86 public void Pshufd(Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, X86Instruction.Pshufd); + WriteInstruction(dest, default, source, X86Instruction.Pshufd); WriteByte(imm); } @@ -773,7 +781,7 @@ namespace ARMeilleure.CodeGen.X86 } else { - WriteInstruction(null, source, source.Type, X86Instruction.Push); + WriteInstruction(default, source, source.Type, X86Instruction.Push); } } @@ -806,12 +814,12 @@ namespace ARMeilleure.CodeGen.X86 { InstructionInfo info = _instTable[(int)X86Instruction.Setcc]; - WriteOpCode(dest, null, null, OperandType.None, info.Flags, info.OpRRM | (int)condition); + WriteOpCode(dest, default, default, OperandType.None, info.Flags, info.OpRRM | (int)condition); } public void Stmxcsr(Operand dest) { - WriteInstruction(dest, null, OperandType.I32, X86Instruction.Stmxcsr); + WriteInstruction(dest, default, OperandType.I32, X86Instruction.Stmxcsr); } public void Sub(Operand dest, Operand source, OperandType type) @@ -850,7 +858,7 @@ namespace ARMeilleure.CodeGen.X86 Operand source, OperandType type = OperandType.None) { - WriteInstruction(dest, null, source, inst, type); + WriteInstruction(dest, default, source, inst, type); } public void WriteInstruction(X86Instruction inst, Operand dest, Operand src1, Operand src2) @@ -877,7 +885,7 @@ namespace ARMeilleure.CodeGen.X86 public void WriteInstruction(X86Instruction inst, Operand dest, Operand source, byte imm) { - WriteInstruction(dest, null, source, inst); + WriteInstruction(dest, default, source, inst); WriteByte(imm); } @@ -917,11 +925,11 @@ namespace ARMeilleure.CodeGen.X86 Debug.Assert(shiftReg == X86Register.Rcx, $"Invalid shift register \"{shiftReg}\"."); - source = null; + source = default; } else if (source.Kind == OperandKind.Constant) { - source = source.With((int)source.Value & (dest.Type == OperandType.I32 ? 0x1f : 0x3f)); + source = Operand.Factory.Const((int)source.Value & (dest.Type == OperandType.I32 ? 0x1f : 0x3f)); } WriteInstruction(dest, source, type, inst); @@ -931,7 +939,7 @@ namespace ARMeilleure.CodeGen.X86 { InstructionInfo info = _instTable[(int)inst]; - if (source != null) + if (source != default) { if (source.Kind == OperandKind.Constant) { @@ -939,29 +947,29 @@ namespace ARMeilleure.CodeGen.X86 if (inst == X86Instruction.Mov8) { - WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm8); + WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8); WriteByte((byte)imm); } else if (inst == X86Instruction.Mov16) { - WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm32); + WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32); WriteInt16((short)imm); } else if (IsImm8(imm, type) && info.OpRMImm8 != BadOp) { - WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm8); + WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8); WriteByte((byte)imm); } else if (!source.Relocatable && IsImm32(imm, type) && info.OpRMImm32 != BadOp) { - WriteOpCode(dest, null, null, type, info.Flags, info.OpRMImm32); + WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32); WriteInt32((int)imm); } - else if (dest?.Kind == OperandKind.Register && info.OpRImm64 != BadOp) + else if (dest != default && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp) { int rexPrefix = GetRexPrefix(dest, source, type, rrm: false); @@ -972,7 +980,7 @@ namespace ARMeilleure.CodeGen.X86 WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111))); - if (_ptcInfo != null && source.Relocatable) + if (_ptcInfo != default && source.Relocatable) { _ptcInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, source.Symbol)); } @@ -986,11 +994,11 @@ namespace ARMeilleure.CodeGen.X86 } else if (source.Kind == OperandKind.Register && info.OpRMR != BadOp) { - WriteOpCode(dest, null, source, type, info.Flags, info.OpRMR); + WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR); } else if (info.OpRRM != BadOp) { - WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM, rrm: true); + WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true); } else { @@ -999,11 +1007,11 @@ namespace ARMeilleure.CodeGen.X86 } else if (info.OpRRM != BadOp) { - WriteOpCode(dest, null, source, type, info.Flags, info.OpRRM, rrm: true); + WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true); } else if (info.OpRMR != BadOp) { - WriteOpCode(dest, null, source, type, info.Flags, info.OpRMR); + WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR); } else { @@ -1020,7 +1028,7 @@ namespace ARMeilleure.CodeGen.X86 { InstructionInfo info = _instTable[(int)inst]; - if (src2 != null) + if (src2 != default) { if (src2.Kind == OperandKind.Constant) { @@ -1028,7 +1036,7 @@ namespace ARMeilleure.CodeGen.X86 if ((byte)imm == imm && info.OpRMImm8 != BadOp) { - WriteOpCode(dest, src1, null, type, info.Flags, info.OpRMImm8); + WriteOpCode(dest, src1, default, type, info.Flags, info.OpRMImm8); WriteByte((byte)imm); } @@ -1082,9 +1090,10 @@ namespace ARMeilleure.CodeGen.X86 int modRM = (opCode >> OpModRMBits) << 3; - MemoryOperand memOp = null; + MemoryOperand memOp = default; + bool hasMemOp = false; - if (dest != null) + if (dest != default) { if (dest.Kind == OperandKind.Register) { @@ -1099,7 +1108,8 @@ namespace ARMeilleure.CodeGen.X86 } else if (dest.Kind == OperandKind.Memory) { - memOp = dest as MemoryOperand; + memOp = dest.GetMemory(); + hasMemOp = true; } else { @@ -1107,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86 } } - if (src2 != null) + if (src2 != default) { if (src2.Kind == OperandKind.Register) { @@ -1120,9 +1130,10 @@ namespace ARMeilleure.CodeGen.X86 rexPrefix |= RexPrefix; } } - else if (src2.Kind == OperandKind.Memory && memOp == null) + else if (src2.Kind == OperandKind.Memory && !hasMemOp) { - memOp = src2 as MemoryOperand; + memOp = src2.GetMemory(); + hasMemOp = true; } else { @@ -1135,14 +1146,14 @@ namespace ARMeilleure.CodeGen.X86 int sib = 0; - if (memOp != null) + if (hasMemOp) { // Either source or destination is a memory operand. Register baseReg = memOp.BaseAddress.GetRegister(); X86Register baseRegLow = (X86Register)(baseReg.Index & 0b111); - needsSibByte = memOp.Index != null || baseRegLow == X86Register.Rsp; + needsSibByte = memOp.Index != default || baseRegLow == X86Register.Rsp; needsDisplacement = memOp.Displacement != 0 || baseRegLow == X86Register.Rbp; if (needsDisplacement) @@ -1168,7 +1179,7 @@ namespace ARMeilleure.CodeGen.X86 { sib = (int)baseRegLow; - if (memOp.Index != null) + if (memOp.Index != default) { int indexReg = memOp.Index.GetRegister().Index; @@ -1217,7 +1228,7 @@ namespace ARMeilleure.CodeGen.X86 _ => 0 }; - if (src1 != null) + if (src1 != default) { vexByte2 |= (src1.GetRegister().Index ^ 0xf) << 3; } @@ -1284,7 +1295,7 @@ namespace ARMeilleure.CodeGen.X86 } } - if (dest != null && (flags & InstructionFlags.RegOnly) != 0) + if (dest != default && (flags & InstructionFlags.RegOnly) != 0) { opCode += dest.GetRegister().Index & 7; } @@ -1353,12 +1364,12 @@ namespace ARMeilleure.CodeGen.X86 } } - if (dest != null && dest.Kind == OperandKind.Register) + if (dest != default && dest.Kind == OperandKind.Register) { SetRegisterHighBit(dest.GetRegister(), rrm ? 2 : 0); } - if (source != null && source.Kind == OperandKind.Register) + if (source != default && source.Kind == OperandKind.Register) { SetRegisterHighBit(source.GetRegister(), rrm ? 0 : 2); } diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 3c14594d..5818eb2e 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -11,8 +11,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Numerics; - -using static ARMeilleure.IntermediateRepresentation.OperandHelper; +using static ARMeilleure.IntermediateRepresentation.Operand.Factory; namespace ARMeilleure.CodeGen.X86 { @@ -162,20 +161,18 @@ namespace ARMeilleure.CodeGen.X86 { context.EnterBlock(block); - for (Node node = block.Operations.First; node != null; node = node.ListNext) + for (Operation node = block.Operations.First; node != default; node = node.ListNext) { - if (node is Operation operation) - { - GenerateOperation(context, operation); - } + GenerateOperation(context, node); } - if (block.SuccessorCount == 0) + if (block.SuccessorsCount == 0) { // The only blocks which can have 0 successors are exit blocks. - Debug.Assert(block.Operations.Last is Operation operation && - (operation.Instruction == Instruction.Tailcall || - operation.Instruction == Instruction.Return)); + Operation last = block.Operations.Last; + + Debug.Assert(last.Instruction == Instruction.Tailcall || + last.Instruction == Instruction.Return); } else { @@ -205,9 +202,7 @@ namespace ARMeilleure.CodeGen.X86 { if (operation.Instruction == Instruction.Extended) { - IntrinsicOperation intrinOp = (IntrinsicOperation)operation; - - IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic); + IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic); switch (info.Type) { @@ -217,7 +212,7 @@ namespace ARMeilleure.CodeGen.X86 Operand src1 = operation.GetSource(0); Operand src2 = operation.GetSource(1); - switch (intrinOp.Intrinsic) + switch (operation.Intrinsic) { case Intrinsic.X86Comisdeq: context.Assembler.Comisd(src1, src2); @@ -266,14 +261,13 @@ namespace ARMeilleure.CodeGen.X86 int offs = offset.AsInt32() + context.CallArgsRegionSize; Operand rsp = Register(X86Register.Rsp); - - MemoryOperand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, offs); + Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, offs); Debug.Assert(HardwareCapabilities.SupportsSse || HardwareCapabilities.SupportsVexEncoding); context.Assembler.Stmxcsr(memOp); - if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb) + if (operation.Intrinsic == Intrinsic.X86Mxcsrmb) { context.Assembler.Or(memOp, bits, OperandType.I32); } @@ -324,7 +318,7 @@ namespace ARMeilleure.CodeGen.X86 Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger()); - if (intrinOp.Intrinsic == Intrinsic.X86Cvtsi2si) + if (operation.Intrinsic == Intrinsic.X86Cvtsi2si) { if (dest.Type == OperandType.I32) { @@ -538,7 +532,7 @@ namespace ARMeilleure.CodeGen.X86 if (src2.Kind == OperandKind.Constant) { offset = src2.AsInt32(); - index = null; + index = default; } else { @@ -546,7 +540,7 @@ namespace ARMeilleure.CodeGen.X86 index = src2; } - MemoryOperand memOp = MemoryOp(dest.Type, src1, index, Multiplier.x1, offset); + Operand memOp = MemoryOp(dest.Type, src1, index, Multiplier.x1, offset); context.Assembler.Lea(dest, memOp, dest.Type); } @@ -720,7 +714,7 @@ namespace ARMeilleure.CodeGen.X86 if (operation.SourcesCount == 5) // CompareAndSwap128 has 5 sources, compared to CompareAndSwap64/32's 3. { - MemoryOperand memOp = MemoryOp(OperandType.I64, src1); + Operand memOp = MemoryOp(OperandType.I64, src1); context.Assembler.Cmpxchg16b(memOp); } @@ -731,7 +725,7 @@ namespace ARMeilleure.CodeGen.X86 EnsureSameType(src2, src3); - MemoryOperand memOp = MemoryOp(src3.Type, src1); + Operand memOp = MemoryOp(src3.Type, src1); context.Assembler.Cmpxchg(memOp, src3); } @@ -745,7 +739,7 @@ namespace ARMeilleure.CodeGen.X86 EnsureSameType(src2, src3); - MemoryOperand memOp = MemoryOp(src3.Type, src1); + Operand memOp = MemoryOp(src3.Type, src1); context.Assembler.Cmpxchg16(memOp, src3); } @@ -758,7 +752,7 @@ namespace ARMeilleure.CodeGen.X86 EnsureSameType(src2, src3); - MemoryOperand memOp = MemoryOp(src3.Type, src1); + Operand memOp = MemoryOp(src3.Type, src1); context.Assembler.Cmpxchg8(memOp, src3); } @@ -954,7 +948,7 @@ namespace ARMeilleure.CodeGen.X86 Operand rsp = Register(X86Register.Rsp); - MemoryOperand memOp = MemoryOp(dest.Type, rsp, null, Multiplier.x1, offs); + Operand memOp = MemoryOp(dest.Type, rsp, default, Multiplier.x1, offs); GenerateLoad(context, memOp, dest); } @@ -1153,7 +1147,7 @@ namespace ARMeilleure.CodeGen.X86 Operand rsp = Register(X86Register.Rsp); - MemoryOperand memOp = MemoryOp(source.Type, rsp, null, Multiplier.x1, offs); + Operand memOp = MemoryOp(source.Type, rsp, default, Multiplier.x1, offs); GenerateStore(context, memOp, source); } @@ -1169,7 +1163,7 @@ namespace ARMeilleure.CodeGen.X86 Operand rsp = Register(X86Register.Rsp); - MemoryOperand memOp = MemoryOp(OperandType.I64, rsp, null, Multiplier.x1, offs); + Operand memOp = MemoryOp(OperandType.I64, rsp, default, Multiplier.x1, offs); context.Assembler.Lea(dest, memOp, OperandType.I64); } @@ -1644,19 +1638,19 @@ namespace ARMeilleure.CodeGen.X86 context.Assembler.Pshufd(dest, dest, 0xfc); } - private static bool MatchOperation(Node node, Instruction inst, OperandType destType, Register destReg) + private static bool MatchOperation(Operation node, Instruction inst, OperandType destType, Register destReg) { - if (!(node is Operation operation) || node.DestinationsCount == 0) + if (node == default || node.DestinationsCount == 0) { return false; } - if (operation.Instruction != inst) + if (node.Instruction != inst) { return false; } - Operand dest = operation.Destination; + Operand dest = node.Destination; return dest.Kind == OperandKind.Register && dest.Type == destType && @@ -1761,7 +1755,7 @@ namespace ARMeilleure.CodeGen.X86 offset -= 16; - MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset); + Operand memOp = MemoryOp(OperandType.V128, rsp, default, Multiplier.x1, offset); context.Assembler.Movdqu(memOp, Xmm((X86Register)bit)); @@ -1791,7 +1785,7 @@ namespace ARMeilleure.CodeGen.X86 offset -= 16; - MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset); + Operand memOp = MemoryOp(OperandType.V128, rsp, default, Multiplier.x1, offset); context.Assembler.Movdqu(Xmm((X86Register)bit), memOp); @@ -1832,17 +1826,17 @@ namespace ARMeilleure.CodeGen.X86 for (int offset = PageSize; offset < size; offset += PageSize) { - Operand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, -offset); + Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, -offset); context.Assembler.Mov(temp, memOp, OperandType.I32); } } - private static MemoryOperand Memory(Operand operand, OperandType type) + private static Operand Memory(Operand operand, OperandType type) { if (operand.Kind == OperandKind.Memory) { - return operand as MemoryOperand; + return operand; } return MemoryOp(type, operand); @@ -1850,12 +1844,12 @@ namespace ARMeilleure.CodeGen.X86 private static Operand Register(X86Register register, OperandType type = OperandType.I64) { - return OperandHelper.Register((int)register, RegisterType.Integer, type); + return Operand.Factory.Register((int)register, RegisterType.Integer, type); } private static Operand Xmm(X86Register register) { - return OperandHelper.Register((int)register, RegisterType.Vector, OperandType.V128); + return Operand.Factory.Register((int)register, RegisterType.Vector, OperandType.V128); } } }
\ No newline at end of file diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs index 3b3fd683..334f8f7e 100644 --- a/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -4,9 +4,8 @@ using ARMeilleure.Translation; using System; using System.Collections.Generic; using System.Diagnostics; - -using static ARMeilleure.IntermediateRepresentation.OperandHelper; -using static ARMeilleure.IntermediateRepresentation.OperationHelper; +using static ARMeilleure.IntermediateRepresentation.Operand.Factory; +using static ARMeilleure.IntermediateRepresentation.Operation.Factory; namespace ARMeilleure.CodeGen.X86 { @@ -22,31 +21,31 @@ namespace ARMeilleure.CodeGen.X86 for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext) { - Node nextNode; + Operation nextNode; - for (Node node = block.Operations.First; node != null; node = nextNode) + for (Operation node = block.Operations.First; node != default; node = nextNode) { nextNode = node.ListNext; - if (node is not Operation operation) + if (node.Instruction == Instruction.Phi) { continue; } - HandleConstantRegCopy(block.Operations, node, operation); - HandleDestructiveRegCopy(block.Operations, node, operation); - HandleConstrainedRegCopy(block.Operations, node, operation); + HandleConstantRegCopy(block.Operations, node); + HandleDestructiveRegCopy(block.Operations, node); + HandleConstrainedRegCopy(block.Operations, node); - switch (operation.Instruction) + switch (node.Instruction) { case Instruction.Call: // Get the maximum number of arguments used on a call. // On windows, when a struct is returned from the call, // we also need to pass the pointer where the struct // should be written on the first argument. - int argsCount = operation.SourcesCount - 1; + int argsCount = node.SourcesCount - 1; - if (operation.Destination != null && operation.Destination.Type == OperandType.V128) + if (node.Destination != default && node.Destination.Type == OperandType.V128) { argsCount++; } @@ -60,72 +59,71 @@ namespace ARMeilleure.CodeGen.X86 // being called, as mandated by the ABI. if (callConv == CallConvName.Windows) { - HandleCallWindowsAbi(block.Operations, stackAlloc, node, operation); + HandleCallWindowsAbi(block.Operations, stackAlloc, node); } else /* if (callConv == CallConvName.SystemV) */ { - HandleCallSystemVAbi(block.Operations, node, operation); + HandleCallSystemVAbi(block.Operations, node); } break; case Instruction.ConvertToFPUI: - HandleConvertToFPUI(block.Operations, node, operation); + HandleConvertToFPUI(block.Operations, node); break; case Instruction.LoadArgument: if (callConv == CallConvName.Windows) { - nextNode = HandleLoadArgumentWindowsAbi(cctx, block.Operations, node, preservedArgs, operation); + nextNode = HandleLoadArgumentWindowsAbi(cctx, block.Operations, preservedArgs, node); } else /* if (callConv == CallConvName.SystemV) */ { - nextNode = HandleLoadArgumentSystemVAbi(cctx, block.Operations, node, preservedArgs, operation); + nextNode = HandleLoadArgumentSystemVAbi(cctx, block.Operations, preservedArgs, node); } break; case Instruction.Negate: - if (!operation.GetSource(0).Type.IsInteger()) + if (!node.GetSource(0).Type.IsInteger()) { - HandleNegate(block.Operations, node, operation); + HandleNegate(block.Operations, node); } break; case Instruction.Return: if (callConv == CallConvName.Windows) { - HandleReturnWindowsAbi(cctx, block.Operations, node, preservedArgs, operation); + HandleReturnWindowsAbi(cctx, block.Operations, preservedArgs, node); } else /* if (callConv == CallConvName.SystemV) */ { - HandleReturnSystemVAbi(block.Operations, node, operation); + HandleReturnSystemVAbi(block.Operations, node); } break; case Instruction.Tailcall: if (callConv == CallConvName.Windows) { - HandleTailcallWindowsAbi(block.Operations, stackAlloc, node, operation); + HandleTailcallWindowsAbi(block.Operations, stackAlloc, node); } else { - HandleTailcallSystemVAbi(block.Operations, stackAlloc, node, operation); + HandleTailcallSystemVAbi(block.Operations, stackAlloc, node); } break; case Instruction.VectorInsert8: if (!HardwareCapabilities.SupportsSse41) { - HandleVectorInsert8(block.Operations, node, operation); + HandleVectorInsert8(block.Operations, node); } break; case Instruction.Extended: - IntrinsicOperation intrinOp = (IntrinsicOperation)operation; - - if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb || intrinOp.Intrinsic == Intrinsic.X86Mxcsrub) + if (node.Intrinsic == Intrinsic.X86Mxcsrmb || node.Intrinsic == Intrinsic.X86Mxcsrub) { int stackOffset = stackAlloc.Allocate(OperandType.I32); - operation.SetSources(new Operand[] { Const(stackOffset), operation.GetSource(0) }); + + node.SetSources(new Operand[] { Const(stackOffset), node.GetSource(0) }); } break; } @@ -133,16 +131,16 @@ namespace ARMeilleure.CodeGen.X86 } } - private static void HandleConstantRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleConstantRegCopy(IntrusiveList<Operation> nodes, Operation node) { - if (operation.SourcesCount == 0 || IsXmmIntrinsic(operation)) + if (node.SourcesCount == 0 || IsXmmIntrinsic(node)) { return; } - Instruction inst = operation.Instruction; + Instruction inst = node.Instruction; - Operand src1 = operation.GetSource(0); + Operand src1 = node.GetSource(0); Operand src2; if (src1.Kind == OperandKind.Constant) @@ -156,7 +154,7 @@ namespace ARMeilleure.CodeGen.X86 // - Replace the constant use with the XMM register. src1 = AddXmmCopy(nodes, node, src1); - operation.SetSource(0, src1); + node.SetSource(0, src1); } else if (!HasConstSrc1(inst)) { @@ -168,34 +166,34 @@ namespace ARMeilleure.CodeGen.X86 // -- Doing so may allow us to encode the constant as operand 2 and avoid a copy. // - If the constant is on operand 2, we check if the instruction supports it, // if not, we also add a copy. 64-bits constants are usually not supported. - if (IsCommutative(operation)) + if (IsCommutative(node)) { - src2 = operation.GetSource(1); + src2 = node.GetSource(1); Operand temp = src1; src1 = src2; src2 = temp; - operation.SetSource(0, src1); - operation.SetSource(1, src2); + node.SetSource(0, src1); + node.SetSource(1, src2); } if (src1.Kind == OperandKind.Constant) { src1 = AddCopy(nodes, node, src1); - operation.SetSource(0, src1); + node.SetSource(0, src1); } } } - if (operation.SourcesCount < 2) + if (node.SourcesCount < 2) { return; } - src2 = operation.GetSource(1); + src2 = node.GetSource(1); if (src2.Kind == OperandKind.Constant) { @@ -203,28 +201,28 @@ namespace ARMeilleure.CodeGen.X86 { src2 = AddXmmCopy(nodes, node, src2); - operation.SetSource(1, src2); + node.SetSource(1, src2); } else if (!HasConstSrc2(inst) || CodeGenCommon.IsLongConst(src2)) { src2 = AddCopy(nodes, node, src2); - operation.SetSource(1, src2); + node.SetSource(1, src2); } } } - private static void HandleConstrainedRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleConstrainedRegCopy(IntrusiveList<Operation> nodes, Operation node) { - Operand dest = operation.Destination; + Operand dest = node.Destination; - switch (operation.Instruction) + switch (node.Instruction) { case Instruction.CompareAndSwap: case Instruction.CompareAndSwap16: case Instruction.CompareAndSwap8: { - OperandType type = operation.GetSource(1).Type; + OperandType type = node.GetSource(1).Type; if (type == OperandType.V128) { @@ -243,14 +241,15 @@ namespace ARMeilleure.CodeGen.X86 Operand rcx = Gpr(X86Register.Rcx, OperandType.I64); Operand rdx = Gpr(X86Register.Rdx, OperandType.I64); - SplitOperand(operation.GetSource(1), rax, rdx); - SplitOperand(operation.GetSource(2), rbx, rcx); + SplitOperand(node.GetSource(1), rax, rdx); + SplitOperand(node.GetSource(2), rbx, rcx); + + Operation operation = node; node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax)); nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1))); operation.SetDestinations(new Operand[] { rdx, rax }); - operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx }); } else @@ -258,8 +257,8 @@ namespace ARMeilleure.CodeGen.X86 // Handle the many restrictions of the compare and exchange (32/64) instruction: // - The expected value should be in (E/R)AX. // - The value at the memory location is loaded to (E/R)AX. - Operand expected = operation.GetSource(1); - Operand newValue = operation.GetSource(2); + Operand expected = node.GetSource(1); + Operand newValue = node.GetSource(2); Operand rax = Gpr(X86Register.Rax, expected.Type); @@ -271,11 +270,11 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue)); - operation.SetSources(new Operand[] { operation.GetSource(0), rax, temp }); + node.SetSources(new Operand[] { node.GetSource(0), rax, temp }); nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax)); - operation.Destination = rax; + node.Destination = rax; } break; @@ -290,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86 // - Additionally it also writes the remainder in RDX. if (dest.Type.IsInteger()) { - Operand src1 = operation.GetSource(0); + Operand src1 = node.GetSource(0); Operand rax = Gpr(X86Register.Rax, src1.Type); Operand rdx = Gpr(X86Register.Rdx, src1.Type); @@ -300,11 +299,8 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax)); - operation.SetDestinations(new Operand[] { rdx, rax }); - - operation.SetSources(new Operand[] { rdx, rax, operation.GetSource(1) }); - - operation.Destination = rax; + node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) }); + node.Destination = rax; } break; @@ -312,19 +308,17 @@ namespace ARMeilleure.CodeGen.X86 case Instruction.Extended: { - IntrinsicOperation intrinOp = (IntrinsicOperation)operation; - // BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported. - if ((intrinOp.Intrinsic == Intrinsic.X86Blendvpd || - intrinOp.Intrinsic == Intrinsic.X86Blendvps || - intrinOp.Intrinsic == Intrinsic.X86Pblendvb) && + if ((node.Intrinsic == Intrinsic.X86Blendvpd || + node.Intrinsic == Intrinsic.X86Blendvps || + node.Intrinsic == Intrinsic.X86Pblendvb) && !HardwareCapabilities.SupportsVexEncoding) { Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128); - nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, operation.GetSource(2))); + nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, node.GetSource(2))); - operation.SetSource(2, xmm0); + node.SetSource(2, xmm0); } break; @@ -337,18 +331,18 @@ namespace ARMeilleure.CodeGen.X86 // - The multiplicand is always in RAX. // - The lower 64-bits of the result is always in RAX. // - The higher 64-bits of the result is always in RDX. - Operand src1 = operation.GetSource(0); + Operand src1 = node.GetSource(0); Operand rax = Gpr(X86Register.Rax, src1.Type); Operand rdx = Gpr(X86Register.Rdx, src1.Type); nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1)); - operation.SetSource(0, rax); + node.SetSource(0, rax); nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx)); - operation.SetDestinations(new Operand[] { rdx, rax }); + node.SetDestinations(new Operand[] { rdx, rax }); break; } @@ -359,13 +353,13 @@ namespace ARMeilleure.CodeGen.X86 case Instruction.ShiftRightUI: { // The shift register is always implied to be CL (low 8-bits of RCX or ECX). - if (operation.GetSource(1).Kind == OperandKind.LocalVariable) + if (node.GetSource(1).Kind == OperandKind.LocalVariable) { Operand rcx = Gpr(X86Register.Rcx, OperandType.I32); - nodes.AddBefore(node, Operation(Instruction.Copy, rcx, operation.GetSource(1))); + nodes.AddBefore(node, Operation(Instruction.Copy, rcx, node.GetSource(1))); - operation.SetSource(1, rcx); + node.SetSource(1, rcx); } break; @@ -373,29 +367,29 @@ namespace ARMeilleure.CodeGen.X86 } } - private static void HandleDestructiveRegCopy(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleDestructiveRegCopy(IntrusiveList<Operation> nodes, Operation node) { - if (operation.Destination == null || operation.SourcesCount == 0) + if (node.Destination == default || node.SourcesCount == 0) { return; } - Instruction inst = operation.Instruction; + Instruction inst = node.Instruction; - Operand dest = operation.Destination; - Operand src1 = operation.GetSource(0); + Operand dest = node.Destination; + Operand src1 = node.GetSource(0); // The multiply instruction (that maps to IMUL) is somewhat special, it has // a three operand form where the second source is a immediate value. - bool threeOperandForm = inst == Instruction.Multiply && operation.GetSource(1).Kind == OperandKind.Constant; + bool threeOperandForm = inst == Instruction.Multiply && node.GetSource(1).Kind == OperandKind.Constant; - if (IsSameOperandDestSrc1(operation) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm) + if (IsSameOperandDestSrc1(node) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm) { bool useNewLocal = false; - for (int srcIndex = 1; srcIndex < operation.SourcesCount; srcIndex++) + for (int srcIndex = 1; srcIndex < node.SourcesCount; srcIndex++) { - if (operation.GetSource(srcIndex) == dest) + if (node.GetSource(srcIndex) == dest) { useNewLocal = true; @@ -412,23 +406,23 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1)); - operation.SetSource(0, temp); + node.SetSource(0, temp); nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp)); - operation.Destination = temp; + node.Destination = temp; } else { nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1)); - operation.SetSource(0, dest); + node.SetSource(0, dest); } } else if (inst == Instruction.ConditionalSelect) { - Operand src2 = operation.GetSource(1); - Operand src3 = operation.GetSource(2); + Operand src2 = node.GetSource(1); + Operand src3 = node.GetSource(2); if (src1 == dest || src2 == dest) { @@ -436,32 +430,32 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddBefore(node, Operation(Instruction.Copy, temp, src3)); - operation.SetSource(2, temp); + node.SetSource(2, temp); nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp)); - operation.Destination = temp; + node.Destination = temp; } else { nodes.AddBefore(node, Operation(Instruction.Copy, dest, src3)); - operation.SetSource(2, dest); + node.SetSource(2, dest); } } } - private static void HandleConvertToFPUI(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleConvertToFPUI(IntrusiveList<Operation> nodes, Operation node) { // Unsigned integer to FP conversions are not supported on X86. // We need to turn them into signed integer to FP conversions, and // adjust the final result. - Operand dest = operation.Destination; - Operand source = operation.GetSource(0); + Operand dest = node.Destination; + Operand source = node.GetSource(0); Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\"."); - Node currentNode = node; + Operation currentNode = node; if (source.Type == OperandType.I32) { @@ -502,21 +496,21 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, lsbF)); } - Delete(nodes, currentNode, operation); + Delete(nodes, currentNode); } - private static void HandleNegate(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleNegate(IntrusiveList<Operation> nodes, Operation node) { // There's no SSE FP negate instruction, so we need to transform that into // a XOR of the value to be negated with a mask with the highest bit set. // This also produces -0 for a negation of the value 0. - Operand dest = operation.Destination; - Operand source = operation.GetSource(0); + Operand dest = node.Destination; + Operand source = node.GetSource(0); Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\"."); - Node currentNode = node; + Operation currentNode = node; Operand res = Local(dest.Type); @@ -524,27 +518,27 @@ namespace ARMeilleure.CodeGen.X86 if (dest.Type == OperandType.FP32) { - node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Pslld, res, res, Const(31))); + node = nodes.AddAfter(node, Operation(Intrinsic.X86Pslld, res, res, Const(31))); } else /* if (dest.Type == OperandType.FP64) */ { - node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Psllq, res, res, Const(63))); + node = nodes.AddAfter(node, Operation(Intrinsic.X86Psllq, res, res, Const(63))); } - node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Xorps, res, res, source)); + node = nodes.AddAfter(node, Operation(Intrinsic.X86Xorps, res, res, source)); nodes.AddAfter(node, Operation(Instruction.Copy, dest, res)); - Delete(nodes, currentNode, operation); + Delete(nodes, currentNode); } - private static void HandleVectorInsert8(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleVectorInsert8(IntrusiveList<Operation> nodes, Operation node) { // Handle vector insertion, when SSE 4.1 is not supported. - Operand dest = operation.Destination; - Operand src1 = operation.GetSource(0); // Vector - Operand src2 = operation.GetSource(1); // Value - Operand src3 = operation.GetSource(2); // Index + Operand dest = node.Destination; + Operand src1 = node.GetSource(0); // Vector + Operand src2 = node.GetSource(1); // Value + Operand src3 = node.GetSource(2); // Index Debug.Assert(src3.Kind == OperandKind.Constant); @@ -552,7 +546,7 @@ namespace ARMeilleure.CodeGen.X86 Debug.Assert(index < 16); - Node currentNode = node; + Operation currentNode = node; Operand temp1 = Local(OperandType.I32); Operand temp2 = Local(OperandType.I32); @@ -580,16 +574,15 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, vinsOp); - Delete(nodes, currentNode, operation); + Delete(nodes, currentNode); } - private static void HandleCallWindowsAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation) + private static void HandleCallWindowsAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node) { - Operand dest = operation.Destination; + Operand dest = node.Destination; // Handle struct arguments. int retArgs = 0; - int stackAllocOffset = 0; int AllocateOnStack(int size) @@ -610,9 +603,9 @@ namespace ARMeilleure.CodeGen.X86 return offset; } - Operand arg0Reg = null; + Operand arg0Reg = default; - if (dest != null && dest.Type == OperandType.V128) + if (dest != default && dest.Type == OperandType.V128) { int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes()); @@ -625,8 +618,7 @@ namespace ARMeilleure.CodeGen.X86 retArgs = 1; } - int argsCount = operation.SourcesCount - 1; - + int argsCount = node.SourcesCount - 1; int maxArgs = CallingConvention.GetArgumentsOnRegsCount() - retArgs; if (argsCount > maxArgs) @@ -636,16 +628,16 @@ namespace ARMeilleure.CodeGen.X86 Operand[] sources = new Operand[1 + retArgs + argsCount]; - sources[0] = operation.GetSource(0); + sources[0] = node.GetSource(0); - if (arg0Reg != null) + if (arg0Reg != default) { sources[1] = arg0Reg; } - for (int index = 1; index < operation.SourcesCount; index++) + for (int index = 1; index < node.SourcesCount; index++) { - Operand source = operation.GetSource(index); + Operand source = node.GetSource(index); if (source.Type == OperandType.V128) { @@ -655,19 +647,18 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset))); - Operation storeOp = Operation(Instruction.Store, null, stackAddr, source); + Operation storeOp = Operation(Instruction.Store, default, stackAddr, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, storeOp), storeOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, storeOp)); - operation.SetSource(index, stackAddr); + node.SetSource(index, stackAddr); } } // Handle arguments passed on registers. for (int index = 0; index < argsCount; index++) { - Operand source = operation.GetSource(index + 1); - + Operand source = node.GetSource(index + 1); Operand argReg; int argIndex = index + retArgs; @@ -683,25 +674,24 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp)); sources[1 + retArgs + index] = argReg; } // The remaining arguments (those that are not passed on registers) // should be passed on the stack, we write them to the stack with "SpillArg". - for (int index = argsCount; index < operation.SourcesCount - 1; index++) + for (int index = argsCount; index < node.SourcesCount - 1; index++) { - Operand source = operation.GetSource(index + 1); - + Operand source = node.GetSource(index + 1); Operand offset = Const((index + retArgs) * 8); - Operation spillOp = Operation(Instruction.SpillArg, null, offset, source); + Operation spillOp = Operation(Instruction.SpillArg, default, offset, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp)); } - if (dest != null) + if (dest != default) { if (dest.Type == OperandType.V128) { @@ -713,7 +703,7 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, loadOp); - operation.Destination = null; + node.Destination = default; } else { @@ -725,23 +715,23 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, copyOp); - operation.Destination = retReg; + node.Destination = retReg; } } - operation.SetSources(sources); + node.SetSources(sources); } - private static void HandleCallSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleCallSystemVAbi(IntrusiveList<Operation> nodes, Operation node) { - Operand dest = operation.Destination; + Operand dest = node.Destination; List<Operand> sources = new List<Operand> { - operation.GetSource(0) + node.GetSource(0) }; - int argsCount = operation.SourcesCount - 1; + int argsCount = node.SourcesCount - 1; int intMax = CallingConvention.GetIntArgumentsOnRegsCount(); int vecMax = CallingConvention.GetVecArgumentsOnRegsCount(); @@ -753,7 +743,7 @@ namespace ARMeilleure.CodeGen.X86 for (int index = 0; index < argsCount; index++) { - Operand source = operation.GetSource(index + 1); + Operand source = node.GetSource(index + 1); bool passOnReg; @@ -790,7 +780,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp)); sources.Add(argReg); } @@ -798,25 +788,27 @@ namespace ARMeilleure.CodeGen.X86 { Operand offset = Const(stackOffset); - Operation spillOp = Operation(Instruction.SpillArg, null, offset, source); + Operation spillOp = Operation(Instruction.SpillArg, default, offset, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp)); stackOffset += source.Type.GetSizeInBytes(); } } - if (dest != null) + if (dest != default) { if (dest.Type == OperandType.V128) { Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); + Operation operation = node; + node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg)); nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1))); - operation.Destination = null; + operation.Destination = default; } else { @@ -828,21 +820,21 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddAfter(node, copyOp); - operation.Destination = retReg; + node.Destination = retReg; } } - operation.SetSources(sources.ToArray()); + node.SetSources(sources.ToArray()); } - private static void HandleTailcallSystemVAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation) + private static void HandleTailcallSystemVAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node) { List<Operand> sources = new List<Operand> { - operation.GetSource(0) + node.GetSource(0) }; - int argsCount = operation.SourcesCount - 1; + int argsCount = node.SourcesCount - 1; int intMax = CallingConvention.GetIntArgumentsOnRegsCount(); int vecMax = CallingConvention.GetVecArgumentsOnRegsCount(); @@ -853,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86 // Handle arguments passed on registers. for (int index = 0; index < argsCount; index++) { - Operand source = operation.GetSource(1 + index); + Operand source = node.GetSource(1 + index); bool passOnReg; @@ -886,7 +878,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp)); sources.Add(argReg); } @@ -901,19 +893,18 @@ namespace ARMeilleure.CodeGen.X86 // callee saved register (which would be trashed on the epilogue). Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); - Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0)); + Operation addrCopyOp = Operation(Instruction.Copy, retReg, node.GetSource(0)); nodes.AddBefore(node, addrCopyOp); sources[0] = retReg; - operation.SetSources(sources.ToArray()); + node.SetSources(sources.ToArray()); } - private static void HandleTailcallWindowsAbi(IntrusiveList<Node> nodes, StackAllocator stackAlloc, Node node, Operation operation) + private static void HandleTailcallWindowsAbi(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node) { - int argsCount = operation.SourcesCount - 1; - + int argsCount = node.SourcesCount - 1; int maxArgs = CallingConvention.GetArgumentsOnRegsCount(); if (argsCount > maxArgs) @@ -926,15 +917,14 @@ namespace ARMeilleure.CodeGen.X86 // Handle arguments passed on registers. for (int index = 0; index < argsCount; index++) { - Operand source = operation.GetSource(1 + index); - + Operand source = node.GetSource(1 + index); Operand argReg = source.Type.IsInteger() ? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type) : Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type); Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp)); sources[1 + index] = argReg; } @@ -944,23 +934,22 @@ namespace ARMeilleure.CodeGen.X86 // callee saved register (which would be trashed on the epilogue). Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); - Operation addrCopyOp = Operation(Instruction.Copy, retReg, operation.GetSource(0)); + Operation addrCopyOp = Operation(Instruction.Copy, retReg, node.GetSource(0)); nodes.AddBefore(node, addrCopyOp); sources[0] = retReg; - operation.SetSources(sources); + node.SetSources(sources); } - private static Node HandleLoadArgumentWindowsAbi( + private static Operation HandleLoadArgumentWindowsAbi( CompilerContext cctx, - IntrusiveList<Node> nodes, - Node node, + IntrusiveList<Operation> nodes, Operand[] preservedArgs, - Operation operation) + Operation node) { - Operand source = operation.GetSource(0); + Operand source = node.GetSource(0); Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind."); @@ -970,28 +959,25 @@ namespace ARMeilleure.CodeGen.X86 if (index < CallingConvention.GetArgumentsOnRegsCount()) { - Operand dest = operation.Destination; + Operand dest = node.Destination; - if (preservedArgs[index] == null) + if (preservedArgs[index] == default) { Operand argReg, pArg; if (dest.Type.IsInteger()) { argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type); - pArg = Local(dest.Type); } else if (dest.Type == OperandType.V128) { argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), OperandType.I64); - pArg = Local(OperandType.I64); } else { argReg = Xmm(CallingConvention.GetVecArgumentRegister(index), dest.Type); - pArg = Local(dest.Type); } @@ -1006,9 +992,9 @@ namespace ARMeilleure.CodeGen.X86 ? Instruction.Load : Instruction.Copy, dest, preservedArgs[index]); - Node newNode = nodes.AddBefore(node, argCopyOp); + Operation newNode = nodes.AddBefore(node, argCopyOp); - Delete(nodes, node, operation); + Delete(nodes, node); return newNode; } @@ -1019,14 +1005,13 @@ namespace ARMeilleure.CodeGen.X86 } } - private static Node HandleLoadArgumentSystemVAbi( + private static Operation HandleLoadArgumentSystemVAbi( CompilerContext cctx, - IntrusiveList<Node> nodes, - Node node, + IntrusiveList<Operation> nodes, Operand[] preservedArgs, - Operation operation) + Operation node) { - Operand source = operation.GetSource(0); + Operand source = node.GetSource(0); Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind."); @@ -1070,9 +1055,9 @@ namespace ARMeilleure.CodeGen.X86 if (passOnReg) { - Operand dest = operation.Destination; + Operand dest = node.Destination; - if (preservedArgs[index] == null) + if (preservedArgs[index] == default) { if (dest.Type == OperandType.V128) { @@ -1108,9 +1093,9 @@ namespace ARMeilleure.CodeGen.X86 Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]); - Node newNode = nodes.AddBefore(node, argCopyOp); + Operation newNode = nodes.AddBefore(node, argCopyOp); - Delete(nodes, node, operation); + Delete(nodes, node); return newNode; } @@ -1123,18 +1108,16 @@ namespace ARMeilleure.CodeGen.X86 private static void HandleReturnWindowsAbi( CompilerContext cctx, - IntrusiveList<Node> nodes, - Node node, + IntrusiveList<Operation> nodes, Operand[] preservedArgs, - Operation operation) + Operation node) { - if (operation.SourcesCount == 0) + if (node.SourcesCount == 0) { return; } - Operand source = operation.GetSource(0); - + Operand source = node.GetSource(0); Operand retReg; if (source.Type.IsInteger()) @@ -1143,10 +1126,9 @@ namespace ARMeilleure.CodeGen.X86 } else if (source.Type == OperandType.V128) { - if (preservedArgs[0] == null) + if (preservedArgs[0] == default) { Operand preservedArg = Local(OperandType.I64); - Operand arg0 = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64); Operation copyOp = Operation(Instruction.Copy, preservedArg, arg0); @@ -1165,7 +1147,7 @@ namespace ARMeilleure.CodeGen.X86 if (source.Type == OperandType.V128) { - Operation retStoreOp = Operation(Instruction.Store, null, retReg, source); + Operation retStoreOp = Operation(Instruction.Store, default, retReg, source); nodes.AddBefore(node, retStoreOp); } @@ -1176,17 +1158,17 @@ namespace ARMeilleure.CodeGen.X86 nodes.AddBefore(node, retCopyOp); } - operation.SetSources(Array.Empty<Operand>()); + node.SetSources(Array.Empty<Operand>()); } - private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void HandleReturnSystemVAbi(IntrusiveList<Operation> nodes, Operation node) { - if (operation.SourcesCount == 0) + if (node.SourcesCount == 0) { return; } - Operand source = operation.GetSource(0); + Operand source = node.GetSource(0); if (source.Type == OperandType.V128) { @@ -1208,10 +1190,9 @@ namespace ARMeilleure.CodeGen.X86 } } - private static Operand AddXmmCopy(IntrusiveList<Node> nodes, Node node, Operand source) + private static Operand AddXmmCopy(IntrusiveList<Operation> nodes, Operation node, Operand source) { Operand temp = Local(source.Type); - Operand intConst = AddCopy(nodes, node, GetIntConst(source)); Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst); @@ -1221,7 +1202,7 @@ namespace ARMeilleure.CodeGen.X86 return temp; } - private static Operand AddCopy(IntrusiveList<Node> nodes, Node node, Operand source) + private static Operand AddCopy(IntrusiveList<Operation> nodes, Operation node, Operand source) { Operand temp = Local(source.Type); @@ -1246,13 +1227,13 @@ namespace ARMeilleure.CodeGen.X86 return value; } - private static void Delete(IntrusiveList<Node> nodes, Node node, Operation operation) + private static void Delete(IntrusiveList<Operation> nodes, Operation node) { - operation.Destination = null; + node.Destination = default; - for (int index = 0; index < operation.SourcesCount; index++) + for (int index = 0; index < node.SourcesCount; index++) { - operation.SetSource(index, null); + node.SetSource(index, default); } nodes.Remove(node); @@ -1307,8 +1288,7 @@ namespace ARMeilleure.CodeGen.X86 private static bool IsIntrinsicSameOperandDestSrc1(Operation operation) { - IntrinsicOperation intrinOp = (IntrinsicOperation)operation; - IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic); + IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic); return info.Type == IntrinsicType.Crc32 || info.Type == IntrinsicType.Fma || IsVexSameOperandDestSrc1(operation); } @@ -1319,7 +1299,7 @@ namespace ARMeilleure.CodeGen.X86 { bool isUnary = operation.SourcesCount < 2; - bool hasVecDest = operation.Destination != null && operation.Destination.Type == OperandType.V128; + bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128; return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest; } @@ -1408,8 +1388,7 @@ namespace ARMeilleure.CodeGen.X86 return false; } - IntrinsicOperation intrinOp = (IntrinsicOperation)operation; - IntrinsicInfo info = IntrinsicTable.GetInfo(intrinOp.Intrinsic); + IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic); return info.Type != IntrinsicType.Crc32; } diff --git a/ARMeilleure/CodeGen/X86/X86Optimizer.cs b/ARMeilleure/CodeGen/X86/X86Optimizer.cs index fa8b54e8..ed040e15 100644 --- a/ARMeilleure/CodeGen/X86/X86Optimizer.cs +++ b/ARMeilleure/CodeGen/X86/X86Optimizer.cs @@ -2,9 +2,8 @@ using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation; using System.Collections.Generic; - -using static ARMeilleure.IntermediateRepresentation.OperandHelper; -using static ARMeilleure.IntermediateRepresentation.OperationHelper; +using static ARMeilleure.IntermediateRepresentation.Operand.Factory; +using static ARMeilleure.IntermediateRepresentation.Operation.Factory; namespace ARMeilleure.CodeGen.X86 { @@ -34,32 +33,27 @@ namespace ARMeilleure.CodeGen.X86 { constants.Clear(); - Node nextNode; + Operation nextNode; - for (Node node = block.Operations.First; node != null; node = nextNode) + for (Operation node = block.Operations.First; node != default; node = nextNode) { nextNode = node.ListNext; - if (!(node is Operation operation)) - { - continue; - } - // Insert copies for constants that can't fit on a 32-bits immediate. // Doing this early unblocks a few optimizations. - if (operation.Instruction == Instruction.Add) + if (node.Instruction == Instruction.Add) { - Operand src1 = operation.GetSource(0); - Operand src2 = operation.GetSource(1); + Operand src1 = node.GetSource(0); + Operand src2 = node.GetSource(1); if (src1.Kind == OperandKind.Constant && (src1.Relocatable || CodeGenCommon.IsLongConst(src1))) { - operation.SetSource(0, GetConstantCopy(block, operation, src1)); + node.SetSource(0, GetConstantCopy(block, node, src1)); } if (src2.Kind == OperandKind.Constant && (src2.Relocatable || CodeGenCommon.IsLongConst(src2))) { - operation.SetSource(1, GetConstantCopy(block, operation, src2)); + node.SetSource(1, GetConstantCopy(block, node, src2)); } } @@ -70,24 +64,24 @@ namespace ARMeilleure.CodeGen.X86 // mov rax, [rax] // Into: // mov rax, [rax+rbx*4+0xcafe] - if (IsMemoryLoadOrStore(operation.Instruction)) + if (IsMemoryLoadOrStore(node.Instruction)) { OperandType type; - if (operation.Destination != null) + if (node.Destination != default) { - type = operation.Destination.Type; + type = node.Destination.Type; } else { - type = operation.GetSource(1).Type; + type = node.GetSource(1).Type; } - MemoryOperand memOp = GetMemoryOperandOrNull(operation.GetSource(0), type); + Operand memOp = GetMemoryOperandOrNull(node.GetSource(0), type); - if (memOp != null) + if (memOp != default) { - operation.SetSource(0, memOp); + node.SetSource(0, memOp); } } } @@ -96,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86 Optimizer.RemoveUnusedNodes(cfg); } - private static MemoryOperand GetMemoryOperandOrNull(Operand addr, OperandType type) + private static Operand GetMemoryOperandOrNull(Operand addr, OperandType type) { Operand baseOp = addr; @@ -117,10 +111,10 @@ namespace ARMeilleure.CodeGen.X86 // If baseOp is still equal to address, then there's nothing that can be optimized. if (baseOp == addr) { - return null; + return default; } - if (imm == 0 && scale == Multiplier.x1 && indexOp != null) + if (imm == 0 && scale == Multiplier.x1 && indexOp != default) { imm = GetConstOp(ref indexOp); } @@ -132,7 +126,7 @@ namespace ARMeilleure.CodeGen.X86 { Operation operation = GetAsgOpWithInst(baseOp, Instruction.Add); - if (operation == null) + if (operation == default) { return 0; } @@ -172,13 +166,13 @@ namespace ARMeilleure.CodeGen.X86 private static (Operand, Multiplier) GetIndexOp(ref Operand baseOp) { - Operand indexOp = null; + Operand indexOp = default; Multiplier scale = Multiplier.x1; Operation addOp = GetAsgOpWithInst(baseOp, Instruction.Add); - if (addOp == null) + if (addOp == default) { return (indexOp, scale); } @@ -198,14 +192,14 @@ namespace ARMeilleure.CodeGen.X86 bool indexOnSrc2 = false; - if (shlOp == null) + if (shlOp == default) { shlOp = GetAsgOpWithInst(src2, Instruction.ShiftLeft); indexOnSrc2 = true; } - if (shlOp != null) + if (shlOp != default) { Operand shSrc = shlOp.GetSource(0); Operand shift = shlOp.GetSource(1); @@ -233,24 +227,19 @@ namespace ARMeilleure.CodeGen.X86 // If we have multiple assignments, folding is not safe // as the value may be different depending on the // control flow path. - if (op.Assignments.Count != 1) + if (op.AssignmentsCount != 1) { - return null; + return default; } - Node asgOp = op.Assignments[0]; - - if (!(asgOp is Operation operation)) - { - return null; - } + Operation asgOp = op.Assignments[0]; - if (operation.Instruction != inst) + if (asgOp.Instruction != inst) { - return null; + return default; } - return operation; + return asgOp; } private static bool IsMemoryLoadOrStore(Instruction inst) |
