Commit 38dcb59d by Sagar Thakur Committed by Jim Stichnoth

[Subzero][MIPS32] Implement sext, zext and trunc

This patch adds support for sext, zext, trunc operations on i8, i16, i32 source operand types. Support for i1 source operand type will follow. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1948093002 . Patch from Sagar Thakur <sagar.thakur@imgtec.com>.
parent 80ee5b3f
......@@ -56,6 +56,7 @@ template <> const char *InstMIPS32La::Opcode = "la";
template <> const char *InstMIPS32Add::Opcode = "add";
template <> const char *InstMIPS32Addu::Opcode = "addu";
template <> const char *InstMIPS32And::Opcode = "and";
template <> const char *InstMIPS32Andi::Opcode = "andi";
template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
template <> const char *InstMIPS32Mflo::Opcode = "mflo";
template <> const char *InstMIPS32Mthi::Opcode = "mthi";
......@@ -65,10 +66,12 @@ template <> const char *InstMIPS32Mult::Opcode = "mult";
template <> const char *InstMIPS32Multu::Opcode = "multu";
template <> const char *InstMIPS32Or::Opcode = "or";
template <> const char *InstMIPS32Ori::Opcode = "ori";
template <> const char *InstMIPS32Sll::Opcode = "sll";
template <> const char *InstMIPS32Slt::Opcode = "slt";
template <> const char *InstMIPS32Slti::Opcode = "slti";
template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
template <> const char *InstMIPS32Sltu::Opcode = "sltu";
template <> const char *InstMIPS32Sra::Opcode = "sra";
template <> const char *InstMIPS32Sub::Opcode = "sub";
template <> const char *InstMIPS32Subu::Opcode = "subu";
template <> const char *InstMIPS32Xor::Opcode = "xor";
......
......@@ -121,6 +121,7 @@ public:
Addiu,
Addu,
And,
Andi,
Br,
Call,
La,
......@@ -137,10 +138,12 @@ public:
Or,
Ori,
Ret,
Sll,
Slt,
Slti,
Sltiu,
Sltu,
Sra,
Sub,
Subu,
Xor,
......@@ -462,6 +465,7 @@ using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>;
using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
......@@ -473,10 +477,12 @@ using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>;
using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>;
using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>;
using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>;
using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>;
using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>;
using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
......
//===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===//
//
// The Subzero Code Generator
//
......@@ -905,20 +904,80 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
void TargetMIPS32::lowerCast(const InstCast *Instr) {
InstCast::OpKind CastKind = Instr->getCastKind();
Variable *Dest = Instr->getDest();
Operand *Src0 = legalizeUndef(Instr->getSrc(0));
const Type DestTy = Dest->getType();
const Type Src0Ty = Src0->getType();
const uint32_t ShiftAmount =
INT32_BITS - (CHAR_BITS * typeWidthInBytes(Src0Ty));
const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(Src0Ty))) - 1;
if (isVectorType(DestTy) || Src0->getType() == IceType_i1) {
UnimplementedLoweringError(this, Instr);
return;
}
switch (CastKind) {
default:
Func->setError("Cast type not supported");
return;
case InstCast::Sext: {
UnimplementedLoweringError(this, Instr);
if (DestTy == IceType_i64) {
auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
Variable *Src0R = legalizeToReg(Src0);
Variable *T_Lo = I32Reg();
if (Src0Ty == IceType_i32) {
_mov(DestLo, Src0R);
} else if (Src0Ty == IceType_i8 || Src0Ty == IceType_i16) {
_sll(T_Lo, Src0R, ShiftAmount);
_sra(DestLo, T_Lo, ShiftAmount);
}
_sra(DestHi, DestLo, INT32_BITS - 1);
} else {
Variable *Src0R = legalizeToReg(Src0);
Variable *T = makeReg(DestTy);
if (Src0Ty == IceType_i8 || Src0Ty == IceType_i16) {
_sll(T, Src0R, ShiftAmount);
_sra(Dest, T, ShiftAmount);
}
}
break;
}
case InstCast::Zext: {
UnimplementedLoweringError(this, Instr);
if (DestTy == IceType_i64) {
auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
Variable *Src0R = legalizeToReg(Src0);
switch (Src0Ty) {
default: { assert(Src0Ty != IceType_i64); } break;
case IceType_i32:
_mov(DestLo, Src0R);
break;
case IceType_i8:
case IceType_i16:
_andi(DestLo, Src0R, Mask);
break;
}
auto *Zero = getZero();
_addiu(DestHi, Zero, 0);
} else {
Variable *Src0R = legalizeToReg(Src0);
Variable *T = makeReg(DestTy);
if (Src0Ty == IceType_i8 || Src0Ty == IceType_i16)
_andi(T, Src0R, Mask);
_mov(Dest, T);
}
break;
}
case InstCast::Trunc: {
UnimplementedLoweringError(this, Instr);
if (Src0Ty == IceType_i64)
Src0 = loOperand(Src0);
Variable *Src0R = legalizeToReg(Src0);
Variable *T = makeReg(DestTy);
_mov(T, Src0R);
_mov(Dest, T);
break;
}
case InstCast::Fptrunc:
......
......@@ -150,6 +150,10 @@ public:
Context.insert<InstMIPS32And>(Dest, Src0, Src1);
}
void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
}
void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
void _ret(Variable *RA, Variable *Src0 = nullptr) {
......@@ -216,6 +220,10 @@ public:
Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
}
void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
}
void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
}
......@@ -232,6 +240,10 @@ public:
Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
}
void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
}
void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
}
......@@ -346,6 +358,8 @@ protected:
static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
SmallBitVector RegsUsed;
VarList PhysicalRegisters[IceType_NUM];
static constexpr uint32_t CHAR_BITS = 8;
static constexpr uint32_t INT32_BITS = 32;
private:
ENABLE_MAKE_UNIQUE;
......
......@@ -799,6 +799,9 @@ entry:
; ARM32-LABEL: trunc64To32Signed
; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Signed
; MIPS32: move v0,a2
define internal i32 @trunc64To16Signed(i64 %a) {
entry:
%conv = trunc i64 %a to i16
......@@ -816,6 +819,11 @@ entry:
; ARM32-LABEL: trunc64To16Signed
; ARM32: sxth r0, r0
; MIPS32-LABEL: trunc64To16Signed
; MIPS32: sll a0,a0,0x10
; MIPS32: sra a0,a0,0x10
; MIPS32: move v0,a0
define internal i32 @trunc64To8Signed(i64 %a) {
entry:
%conv = trunc i64 %a to i8
......@@ -833,6 +841,11 @@ entry:
; ARM32-LABEL: trunc64To8Signed
; ARM32: sxtb r0, r0
; MIPS32-LABEL: trunc64To8Signed
; MIPS32: sll a0,a0,0x18
; MIPS32: sra a0,a0,0x18
; MIPS32: move v0,a0
define internal i32 @trunc64To32SignedConst() {
entry:
%conv = trunc i64 12345678901234 to i32
......@@ -848,6 +861,10 @@ entry:
; ARM32: movw r0, #12274 ; 0x2ff2
; ARM32: movt r0, #29646 ; 0x73ce
; MIPS32-LABEL: trunc64To32SignedConst
; MIPS32: lui v0,0x73ce
; MIPS32: ori v0,v0,0x2ff2
define internal i32 @trunc64To16SignedConst() {
entry:
%conv = trunc i64 12345678901234 to i16
......@@ -867,6 +884,12 @@ entry:
; ARM32: movt r0, #29646 ; 0x73ce
; ARM32: sxth r0, r0
; MIPS32-LABEL: trunc64To16SignedConst
; MIPS32: lui v0,0x73ce
; MIPS32: ori v0,v0,0x2ff2
; MIPS32: sll v0,v0,0x10
; MIPS32: sra v0,v0,0x10
define internal i32 @trunc64To32Unsigned(i64 %padding, i64 %a) {
entry:
%conv = trunc i64 %a to i32
......@@ -881,6 +904,9 @@ entry:
; ARM32-LABEL: trunc64To32Unsigned
; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Unsigned
; MIPS32: move v0,a2
define internal i32 @trunc64To16Unsigned(i64 %a) {
entry:
%conv = trunc i64 %a to i16
......@@ -898,6 +924,10 @@ entry:
; ARM32-LABEL: trunc64To16Unsigned
; ARM32: uxth
; MIPS32-LABEL: trunc64To16Unsigned
; MIPS32: andi a0,a0,0xffff
; MIPS32: move v0,a0
define internal i32 @trunc64To8Unsigned(i64 %a) {
entry:
%conv = trunc i64 %a to i8
......@@ -915,6 +945,10 @@ entry:
; ARM32-LABEL: trunc64To8Unsigned
; ARM32: uxtb
; MIPS32-LABEL: trunc64To8Unsigned
; MIPS32: andi a0,a0,0xff
; MIPS32: move v0,a0
define internal i32 @trunc64To1(i64 %a) {
entry:
; %tobool = icmp ne i64 %a, 0
......@@ -952,6 +986,10 @@ entry:
; ARM32-LABEL: sext32To64
; ARM32: asr {{.*}}, #31
; MIPS32-LABEL: sext32To64
; MIPS32-LABEL: sra v1,a0,0x1f
; MIPS32-LABEL: move v0,a0
define internal i64 @sext16To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i16
......@@ -970,6 +1008,12 @@ entry:
; ARM32: sxth
; ARM32: asr {{.*}}, #31
; MIPS32-LABEL: sext16To64
; MIPS32: sll a0,a0,0x10
; MIPS32: sra a0,a0,0x10
; MIPS32: sra v1,a0,0x1f
; MIPS32: move v0,a0
define internal i64 @sext8To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i8
......@@ -988,6 +1032,12 @@ entry:
; ARM32: sxtb
; ARM32: asr {{.*}}, #31
; MIPS32-LABEL: sext8To64
; MIPS32: sll a0,a0,0x18
; MIPS32: sra a0,a0,0x18
; MIPS32: sra v1,a0,0x1f
; MIPS32: move v0,a0
define internal i64 @sext1To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i1
......@@ -1026,6 +1076,10 @@ entry:
; ARM32-LABEL: zext32To64
; ARM32: mov {{.*}}, #0
; MIPS32-LABEL: zext32To64
; MIPS32: li v1,0
; MIPS32: move v0,a0
define internal i64 @zext16To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i16
......@@ -1044,6 +1098,11 @@ entry:
; ARM32: uxth
; ARM32: mov {{.*}}, #0
; MIPS32-LABEL: zext16To64
; MIPS32: andi a0,a0,0xffff
; MIPS32: li v1,0
; MIPS32: move v0,a0
define internal i64 @zext8To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i8
......@@ -1062,6 +1121,11 @@ entry:
; ARM32: uxtb
; ARM32: mov {{.*}}, #0
; MIPS32-LABEL: zext8To64
; MIPS32: andi a0,a0,0xff
; MIPS32: li v1,0
; MIPS32: move v0,a0
define internal i64 @zext1To64(i32 %a) {
entry:
%a.arg_trunc = trunc i32 %a to i1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment