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"; ...@@ -56,6 +56,7 @@ template <> const char *InstMIPS32La::Opcode = "la";
template <> const char *InstMIPS32Add::Opcode = "add"; template <> const char *InstMIPS32Add::Opcode = "add";
template <> const char *InstMIPS32Addu::Opcode = "addu"; template <> const char *InstMIPS32Addu::Opcode = "addu";
template <> const char *InstMIPS32And::Opcode = "and"; template <> const char *InstMIPS32And::Opcode = "and";
template <> const char *InstMIPS32Andi::Opcode = "andi";
template <> const char *InstMIPS32Mfhi::Opcode = "mfhi"; template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
template <> const char *InstMIPS32Mflo::Opcode = "mflo"; template <> const char *InstMIPS32Mflo::Opcode = "mflo";
template <> const char *InstMIPS32Mthi::Opcode = "mthi"; template <> const char *InstMIPS32Mthi::Opcode = "mthi";
...@@ -65,10 +66,12 @@ template <> const char *InstMIPS32Mult::Opcode = "mult"; ...@@ -65,10 +66,12 @@ template <> const char *InstMIPS32Mult::Opcode = "mult";
template <> const char *InstMIPS32Multu::Opcode = "multu"; template <> const char *InstMIPS32Multu::Opcode = "multu";
template <> const char *InstMIPS32Or::Opcode = "or"; template <> const char *InstMIPS32Or::Opcode = "or";
template <> const char *InstMIPS32Ori::Opcode = "ori"; template <> const char *InstMIPS32Ori::Opcode = "ori";
template <> const char *InstMIPS32Sll::Opcode = "sll";
template <> const char *InstMIPS32Slt::Opcode = "slt"; template <> const char *InstMIPS32Slt::Opcode = "slt";
template <> const char *InstMIPS32Slti::Opcode = "slti"; template <> const char *InstMIPS32Slti::Opcode = "slti";
template <> const char *InstMIPS32Sltiu::Opcode = "sltiu"; template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
template <> const char *InstMIPS32Sltu::Opcode = "sltu"; template <> const char *InstMIPS32Sltu::Opcode = "sltu";
template <> const char *InstMIPS32Sra::Opcode = "sra";
template <> const char *InstMIPS32Sub::Opcode = "sub"; template <> const char *InstMIPS32Sub::Opcode = "sub";
template <> const char *InstMIPS32Subu::Opcode = "subu"; template <> const char *InstMIPS32Subu::Opcode = "subu";
template <> const char *InstMIPS32Xor::Opcode = "xor"; template <> const char *InstMIPS32Xor::Opcode = "xor";
......
...@@ -121,6 +121,7 @@ public: ...@@ -121,6 +121,7 @@ public:
Addiu, Addiu,
Addu, Addu,
And, And,
Andi,
Br, Br,
Call, Call,
La, La,
...@@ -137,10 +138,12 @@ public: ...@@ -137,10 +138,12 @@ public:
Or, Or,
Ori, Ori,
Ret, Ret,
Sll,
Slt, Slt,
Slti, Slti,
Sltiu, Sltiu,
Sltu, Sltu,
Sra,
Sub, Sub,
Subu, Subu,
Xor, Xor,
...@@ -462,6 +465,7 @@ using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>; ...@@ -462,6 +465,7 @@ using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>; using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>; using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>; using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>; using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>;
using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>; using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>; using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
...@@ -473,10 +477,12 @@ using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>; ...@@ -473,10 +477,12 @@ using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>; using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>; using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>; using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>;
using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>; using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>;
using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>; using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>;
using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>; using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>;
using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>; using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>;
using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>;
using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>; using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>; using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>; using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
......
//===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===//
// //
// The Subzero Code Generator // The Subzero Code Generator
// //
...@@ -905,20 +904,80 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) { ...@@ -905,20 +904,80 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
void TargetMIPS32::lowerCast(const InstCast *Instr) { void TargetMIPS32::lowerCast(const InstCast *Instr) {
InstCast::OpKind CastKind = Instr->getCastKind(); 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) { switch (CastKind) {
default: default:
Func->setError("Cast type not supported"); Func->setError("Cast type not supported");
return; return;
case InstCast::Sext: { 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; break;
} }
case InstCast::Zext: { 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; break;
} }
case InstCast::Trunc: { 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; break;
} }
case InstCast::Fptrunc: case InstCast::Fptrunc:
......
...@@ -150,6 +150,10 @@ public: ...@@ -150,6 +150,10 @@ public:
Context.insert<InstMIPS32And>(Dest, Src0, Src1); 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 _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
void _ret(Variable *RA, Variable *Src0 = nullptr) { void _ret(Variable *RA, Variable *Src0 = nullptr) {
...@@ -216,6 +220,10 @@ public: ...@@ -216,6 +220,10 @@ public:
Context.insert<InstMIPS32Ori>(Dest, Src, Imm); 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) { void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Slt>(Dest, Src0, Src1); Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
} }
...@@ -232,6 +240,10 @@ public: ...@@ -232,6 +240,10 @@ public:
Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1); 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) { void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Sub>(Dest, Src0, Src1); Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
} }
...@@ -346,6 +358,8 @@ protected: ...@@ -346,6 +358,8 @@ protected:
static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM]; static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
SmallBitVector RegsUsed; SmallBitVector RegsUsed;
VarList PhysicalRegisters[IceType_NUM]; VarList PhysicalRegisters[IceType_NUM];
static constexpr uint32_t CHAR_BITS = 8;
static constexpr uint32_t INT32_BITS = 32;
private: private:
ENABLE_MAKE_UNIQUE; ENABLE_MAKE_UNIQUE;
......
...@@ -799,6 +799,9 @@ entry: ...@@ -799,6 +799,9 @@ entry:
; ARM32-LABEL: trunc64To32Signed ; ARM32-LABEL: trunc64To32Signed
; ARM32: mov r0, r2 ; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Signed
; MIPS32: move v0,a2
define internal i32 @trunc64To16Signed(i64 %a) { define internal i32 @trunc64To16Signed(i64 %a) {
entry: entry:
%conv = trunc i64 %a to i16 %conv = trunc i64 %a to i16
...@@ -816,6 +819,11 @@ entry: ...@@ -816,6 +819,11 @@ entry:
; ARM32-LABEL: trunc64To16Signed ; ARM32-LABEL: trunc64To16Signed
; ARM32: sxth r0, r0 ; 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) { define internal i32 @trunc64To8Signed(i64 %a) {
entry: entry:
%conv = trunc i64 %a to i8 %conv = trunc i64 %a to i8
...@@ -833,6 +841,11 @@ entry: ...@@ -833,6 +841,11 @@ entry:
; ARM32-LABEL: trunc64To8Signed ; ARM32-LABEL: trunc64To8Signed
; ARM32: sxtb r0, r0 ; 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() { define internal i32 @trunc64To32SignedConst() {
entry: entry:
%conv = trunc i64 12345678901234 to i32 %conv = trunc i64 12345678901234 to i32
...@@ -848,6 +861,10 @@ entry: ...@@ -848,6 +861,10 @@ entry:
; ARM32: movw r0, #12274 ; 0x2ff2 ; ARM32: movw r0, #12274 ; 0x2ff2
; ARM32: movt r0, #29646 ; 0x73ce ; ARM32: movt r0, #29646 ; 0x73ce
; MIPS32-LABEL: trunc64To32SignedConst
; MIPS32: lui v0,0x73ce
; MIPS32: ori v0,v0,0x2ff2
define internal i32 @trunc64To16SignedConst() { define internal i32 @trunc64To16SignedConst() {
entry: entry:
%conv = trunc i64 12345678901234 to i16 %conv = trunc i64 12345678901234 to i16
...@@ -867,6 +884,12 @@ entry: ...@@ -867,6 +884,12 @@ entry:
; ARM32: movt r0, #29646 ; 0x73ce ; ARM32: movt r0, #29646 ; 0x73ce
; ARM32: sxth r0, r0 ; 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) { define internal i32 @trunc64To32Unsigned(i64 %padding, i64 %a) {
entry: entry:
%conv = trunc i64 %a to i32 %conv = trunc i64 %a to i32
...@@ -881,6 +904,9 @@ entry: ...@@ -881,6 +904,9 @@ entry:
; ARM32-LABEL: trunc64To32Unsigned ; ARM32-LABEL: trunc64To32Unsigned
; ARM32: mov r0, r2 ; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Unsigned
; MIPS32: move v0,a2
define internal i32 @trunc64To16Unsigned(i64 %a) { define internal i32 @trunc64To16Unsigned(i64 %a) {
entry: entry:
%conv = trunc i64 %a to i16 %conv = trunc i64 %a to i16
...@@ -898,6 +924,10 @@ entry: ...@@ -898,6 +924,10 @@ entry:
; ARM32-LABEL: trunc64To16Unsigned ; ARM32-LABEL: trunc64To16Unsigned
; ARM32: uxth ; ARM32: uxth
; MIPS32-LABEL: trunc64To16Unsigned
; MIPS32: andi a0,a0,0xffff
; MIPS32: move v0,a0
define internal i32 @trunc64To8Unsigned(i64 %a) { define internal i32 @trunc64To8Unsigned(i64 %a) {
entry: entry:
%conv = trunc i64 %a to i8 %conv = trunc i64 %a to i8
...@@ -915,6 +945,10 @@ entry: ...@@ -915,6 +945,10 @@ entry:
; ARM32-LABEL: trunc64To8Unsigned ; ARM32-LABEL: trunc64To8Unsigned
; ARM32: uxtb ; ARM32: uxtb
; MIPS32-LABEL: trunc64To8Unsigned
; MIPS32: andi a0,a0,0xff
; MIPS32: move v0,a0
define internal i32 @trunc64To1(i64 %a) { define internal i32 @trunc64To1(i64 %a) {
entry: entry:
; %tobool = icmp ne i64 %a, 0 ; %tobool = icmp ne i64 %a, 0
...@@ -952,6 +986,10 @@ entry: ...@@ -952,6 +986,10 @@ entry:
; ARM32-LABEL: sext32To64 ; ARM32-LABEL: sext32To64
; ARM32: asr {{.*}}, #31 ; ARM32: asr {{.*}}, #31
; MIPS32-LABEL: sext32To64
; MIPS32-LABEL: sra v1,a0,0x1f
; MIPS32-LABEL: move v0,a0
define internal i64 @sext16To64(i32 %a) { define internal i64 @sext16To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i16 %a.arg_trunc = trunc i32 %a to i16
...@@ -970,6 +1008,12 @@ entry: ...@@ -970,6 +1008,12 @@ entry:
; ARM32: sxth ; ARM32: sxth
; ARM32: asr {{.*}}, #31 ; 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) { define internal i64 @sext8To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i8 %a.arg_trunc = trunc i32 %a to i8
...@@ -988,6 +1032,12 @@ entry: ...@@ -988,6 +1032,12 @@ entry:
; ARM32: sxtb ; ARM32: sxtb
; ARM32: asr {{.*}}, #31 ; 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) { define internal i64 @sext1To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i1 %a.arg_trunc = trunc i32 %a to i1
...@@ -1026,6 +1076,10 @@ entry: ...@@ -1026,6 +1076,10 @@ entry:
; ARM32-LABEL: zext32To64 ; ARM32-LABEL: zext32To64
; ARM32: mov {{.*}}, #0 ; ARM32: mov {{.*}}, #0
; MIPS32-LABEL: zext32To64
; MIPS32: li v1,0
; MIPS32: move v0,a0
define internal i64 @zext16To64(i32 %a) { define internal i64 @zext16To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i16 %a.arg_trunc = trunc i32 %a to i16
...@@ -1044,6 +1098,11 @@ entry: ...@@ -1044,6 +1098,11 @@ entry:
; ARM32: uxth ; ARM32: uxth
; ARM32: mov {{.*}}, #0 ; 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) { define internal i64 @zext8To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i8 %a.arg_trunc = trunc i32 %a to i8
...@@ -1062,6 +1121,11 @@ entry: ...@@ -1062,6 +1121,11 @@ entry:
; ARM32: uxtb ; ARM32: uxtb
; ARM32: mov {{.*}}, #0 ; 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) { define internal i64 @zext1To64(i32 %a) {
entry: entry:
%a.arg_trunc = trunc i32 %a to i1 %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