Commit cac003e8 by Jim Stichnoth

Subzero: Add more kinds of RMW lowering.

Specifically: sub, and, or, xor; for all integer types. Turns out that RMW is not possible for fadd/fsub/fmul/fdiv as well as operations on vector types, because the corresponding x86 instructions require the result to be in a physical register. Refactors the assembler's implementations of add/or/adc/sbb/and/sub/xor/cmp to avoid repetition. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4095 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1186713010
parent a9eeb420
...@@ -708,14 +708,20 @@ public: ...@@ -708,14 +708,20 @@ public:
void And(Type Ty, GPRRegister dst, GPRRegister src); void And(Type Ty, GPRRegister dst, GPRRegister src);
void And(Type Ty, GPRRegister dst, const Address &address); void And(Type Ty, GPRRegister dst, const Address &address);
void And(Type Ty, GPRRegister dst, const Immediate &imm); void And(Type Ty, GPRRegister dst, const Immediate &imm);
void And(Type Ty, const Address &address, GPRRegister reg);
void And(Type Ty, const Address &address, const Immediate &imm);
void Or(Type Ty, GPRRegister dst, GPRRegister src); void Or(Type Ty, GPRRegister dst, GPRRegister src);
void Or(Type Ty, GPRRegister dst, const Address &address); void Or(Type Ty, GPRRegister dst, const Address &address);
void Or(Type Ty, GPRRegister dst, const Immediate &imm); void Or(Type Ty, GPRRegister dst, const Immediate &imm);
void Or(Type Ty, const Address &address, GPRRegister reg);
void Or(Type Ty, const Address &address, const Immediate &imm);
void Xor(Type Ty, GPRRegister dst, GPRRegister src); void Xor(Type Ty, GPRRegister dst, GPRRegister src);
void Xor(Type Ty, GPRRegister dst, const Address &address); void Xor(Type Ty, GPRRegister dst, const Address &address);
void Xor(Type Ty, GPRRegister dst, const Immediate &imm); void Xor(Type Ty, GPRRegister dst, const Immediate &imm);
void Xor(Type Ty, const Address &address, GPRRegister reg);
void Xor(Type Ty, const Address &address, const Immediate &imm);
void add(Type Ty, GPRRegister dst, GPRRegister src); void add(Type Ty, GPRRegister dst, GPRRegister src);
void add(Type Ty, GPRRegister reg, const Address &address); void add(Type Ty, GPRRegister reg, const Address &address);
...@@ -726,14 +732,20 @@ public: ...@@ -726,14 +732,20 @@ public:
void adc(Type Ty, GPRRegister dst, GPRRegister src); void adc(Type Ty, GPRRegister dst, GPRRegister src);
void adc(Type Ty, GPRRegister dst, const Address &address); void adc(Type Ty, GPRRegister dst, const Address &address);
void adc(Type Ty, GPRRegister reg, const Immediate &imm); void adc(Type Ty, GPRRegister reg, const Immediate &imm);
void adc(Type Ty, const Address &address, GPRRegister reg);
void adc(Type Ty, const Address &address, const Immediate &imm);
void sub(Type Ty, GPRRegister dst, GPRRegister src); void sub(Type Ty, GPRRegister dst, GPRRegister src);
void sub(Type Ty, GPRRegister reg, const Address &address); void sub(Type Ty, GPRRegister reg, const Address &address);
void sub(Type Ty, GPRRegister reg, const Immediate &imm); void sub(Type Ty, GPRRegister reg, const Immediate &imm);
void sub(Type Ty, const Address &address, GPRRegister reg);
void sub(Type Ty, const Address &address, const Immediate &imm);
void sbb(Type Ty, GPRRegister dst, GPRRegister src); void sbb(Type Ty, GPRRegister dst, GPRRegister src);
void sbb(Type Ty, GPRRegister reg, const Address &address); void sbb(Type Ty, GPRRegister reg, const Address &address);
void sbb(Type Ty, GPRRegister reg, const Immediate &imm); void sbb(Type Ty, GPRRegister reg, const Immediate &imm);
void sbb(Type Ty, const Address &address, GPRRegister reg);
void sbb(Type Ty, const Address &address, const Immediate &imm);
void cbw(); void cbw();
void cwd(); void cwd();
...@@ -859,6 +871,24 @@ private: ...@@ -859,6 +871,24 @@ private:
LabelVector LocalLabels; LabelVector LocalLabels;
Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels); Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels);
// The arith_int() methods factor out the commonality between the encodings of
// add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
// parameter is statically asserted to be less than 8.
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg, const Immediate &imm);
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg0, GPRRegister reg1);
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg, const Address &address);
template <uint32_t Tag>
void arith_int(Type Ty, const Address &address, GPRRegister reg);
template <uint32_t Tag>
void arith_int(Type Ty, const Address &address, const Immediate &imm);
}; };
inline void AssemblerX8632::emitUint8(uint8_t value) { inline void AssemblerX8632::emitUint8(uint8_t value) {
......
...@@ -390,8 +390,9 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, ...@@ -390,8 +390,9 @@ void ELFObjectWriter::writeDataOfType(SectionType ST,
for (VariableDeclaration::Initializer *Init : Var->getInitializers()) { for (VariableDeclaration::Initializer *Init : Var->getInitializers()) {
switch (Init->getKind()) { switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: { case VariableDeclaration::Initializer::DataInitializerKind: {
const auto Data = llvm::cast<VariableDeclaration::DataInitializer>( const auto Data =
Init)->getContents(); llvm::cast<VariableDeclaration::DataInitializer>(Init)
->getContents();
Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
break; break;
} }
......
...@@ -364,9 +364,7 @@ void GlobalContext::emitFileHeader() { ...@@ -364,9 +364,7 @@ void GlobalContext::emitFileHeader() {
} }
} }
void GlobalContext::lowerConstants() { void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
DataLowering->lowerConstants();
}
void GlobalContext::lowerGlobals(const IceString &SectionSuffix) { void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
TimerMarker T(TimerStack::TT_emitGlobalInitializers, this); TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
......
...@@ -937,19 +937,25 @@ template <> const char *InstX8632Add::Opcode = "add"; ...@@ -937,19 +937,25 @@ template <> const char *InstX8632Add::Opcode = "add";
template <> const char *InstX8632AddRMW::Opcode = "add"; template <> const char *InstX8632AddRMW::Opcode = "add";
template <> const char *InstX8632Addps::Opcode = "addps"; template <> const char *InstX8632Addps::Opcode = "addps";
template <> const char *InstX8632Adc::Opcode = "adc"; template <> const char *InstX8632Adc::Opcode = "adc";
template <> const char *InstX8632AdcRMW::Opcode = "adc";
template <> const char *InstX8632Addss::Opcode = "addss"; template <> const char *InstX8632Addss::Opcode = "addss";
template <> const char *InstX8632Padd::Opcode = "padd"; template <> const char *InstX8632Padd::Opcode = "padd";
template <> const char *InstX8632Sub::Opcode = "sub"; template <> const char *InstX8632Sub::Opcode = "sub";
template <> const char *InstX8632SubRMW::Opcode = "sub";
template <> const char *InstX8632Subps::Opcode = "subps"; template <> const char *InstX8632Subps::Opcode = "subps";
template <> const char *InstX8632Subss::Opcode = "subss"; template <> const char *InstX8632Subss::Opcode = "subss";
template <> const char *InstX8632Sbb::Opcode = "sbb"; template <> const char *InstX8632Sbb::Opcode = "sbb";
template <> const char *InstX8632SbbRMW::Opcode = "sbb";
template <> const char *InstX8632Psub::Opcode = "psub"; template <> const char *InstX8632Psub::Opcode = "psub";
template <> const char *InstX8632And::Opcode = "and"; template <> const char *InstX8632And::Opcode = "and";
template <> const char *InstX8632AndRMW::Opcode = "and";
template <> const char *InstX8632Pand::Opcode = "pand"; template <> const char *InstX8632Pand::Opcode = "pand";
template <> const char *InstX8632Pandn::Opcode = "pandn"; template <> const char *InstX8632Pandn::Opcode = "pandn";
template <> const char *InstX8632Or::Opcode = "or"; template <> const char *InstX8632Or::Opcode = "or";
template <> const char *InstX8632OrRMW::Opcode = "or";
template <> const char *InstX8632Por::Opcode = "por"; template <> const char *InstX8632Por::Opcode = "por";
template <> const char *InstX8632Xor::Opcode = "xor"; template <> const char *InstX8632Xor::Opcode = "xor";
template <> const char *InstX8632XorRMW::Opcode = "xor";
template <> const char *InstX8632Pxor::Opcode = "pxor"; template <> const char *InstX8632Pxor::Opcode = "pxor";
template <> const char *InstX8632Imul::Opcode = "imul"; template <> const char *InstX8632Imul::Opcode = "imul";
template <> const char *InstX8632Mulps::Opcode = "mulps"; template <> const char *InstX8632Mulps::Opcode = "mulps";
...@@ -1025,25 +1031,43 @@ const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Adc::Emitter = { ...@@ -1025,25 +1031,43 @@ const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Adc::Emitter = {
&X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc,
&X8632::AssemblerX8632::adc}; &X8632::AssemblerX8632::adc};
template <> template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AdcRMW::Emitter = {
&X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc};
template <>
const X8632::AssemblerX8632::GPREmitterRegOp InstX8632And::Emitter = { const X8632::AssemblerX8632::GPREmitterRegOp InstX8632And::Emitter = {
&X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And,
&X8632::AssemblerX8632::And}; &X8632::AssemblerX8632::And};
template <> template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AndRMW::Emitter = {
&X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And};
template <>
const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Or::Emitter = { const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Or::Emitter = {
&X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or,
&X8632::AssemblerX8632::Or}; &X8632::AssemblerX8632::Or};
template <> template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632OrRMW::Emitter = {
&X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or};
template <>
const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sbb::Emitter = { const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sbb::Emitter = {
&X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb,
&X8632::AssemblerX8632::sbb}; &X8632::AssemblerX8632::sbb};
template <> template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SbbRMW::Emitter = {
&X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb};
template <>
const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sub::Emitter = { const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sub::Emitter = {
&X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub,
&X8632::AssemblerX8632::sub}; &X8632::AssemblerX8632::sub};
template <> template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SubRMW::Emitter = {
&X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub};
template <>
const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Xor::Emitter = { const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Xor::Emitter = {
&X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor,
&X8632::AssemblerX8632::Xor}; &X8632::AssemblerX8632::Xor};
template <>
const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632XorRMW::Emitter = {
&X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor};
// Binary Shift GPR ops // Binary Shift GPR ops
template <> template <>
......
...@@ -175,12 +175,14 @@ public: ...@@ -175,12 +175,14 @@ public:
enum InstKindX8632 { enum InstKindX8632 {
k__Start = Inst::Target, k__Start = Inst::Target,
Adc, Adc,
AdcRMW,
Add, Add,
AddRMW, AddRMW,
Addps, Addps,
Addss, Addss,
Adjuststack, Adjuststack,
And, And,
AndRMW,
Blendvps, Blendvps,
Br, Br,
Bsf, Bsf,
...@@ -221,6 +223,7 @@ public: ...@@ -221,6 +223,7 @@ public:
Neg, Neg,
Nop, Nop,
Or, Or,
OrRMW,
Padd, Padd,
Pand, Pand,
Pandn, Pandn,
...@@ -244,6 +247,7 @@ public: ...@@ -244,6 +247,7 @@ public:
Rol, Rol,
Sar, Sar,
Sbb, Sbb,
SbbRMW,
Setcc, Setcc,
Shl, Shl,
Shld, Shld,
...@@ -255,6 +259,7 @@ public: ...@@ -255,6 +259,7 @@ public:
StoreP, StoreP,
StoreQ, StoreQ,
Sub, Sub,
SubRMW,
Subps, Subps,
Subss, Subss,
Test, Test,
...@@ -262,7 +267,8 @@ public: ...@@ -262,7 +267,8 @@ public:
UD2, UD2,
Xadd, Xadd,
Xchg, Xchg,
Xor Xor,
XorRMW
}; };
static const char *getWidthString(Type Ty); static const char *getWidthString(Type Ty);
...@@ -1103,19 +1109,25 @@ typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add; ...@@ -1103,19 +1109,25 @@ typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add;
typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW; typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW;
typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps; typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps;
typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc; typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc;
typedef InstX8632BinopRMW<InstX8632::AdcRMW> InstX8632AdcRMW;
typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss; typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss;
typedef InstX8632BinopXmm<InstX8632::Padd, true> InstX8632Padd; typedef InstX8632BinopXmm<InstX8632::Padd, true> InstX8632Padd;
typedef InstX8632BinopGPR<InstX8632::Sub> InstX8632Sub; typedef InstX8632BinopGPR<InstX8632::Sub> InstX8632Sub;
typedef InstX8632BinopRMW<InstX8632::SubRMW> InstX8632SubRMW;
typedef InstX8632BinopXmm<InstX8632::Subps, true> InstX8632Subps; typedef InstX8632BinopXmm<InstX8632::Subps, true> InstX8632Subps;
typedef InstX8632BinopXmm<InstX8632::Subss, false> InstX8632Subss; typedef InstX8632BinopXmm<InstX8632::Subss, false> InstX8632Subss;
typedef InstX8632BinopGPR<InstX8632::Sbb> InstX8632Sbb; typedef InstX8632BinopGPR<InstX8632::Sbb> InstX8632Sbb;
typedef InstX8632BinopRMW<InstX8632::SbbRMW> InstX8632SbbRMW;
typedef InstX8632BinopXmm<InstX8632::Psub, true> InstX8632Psub; typedef InstX8632BinopXmm<InstX8632::Psub, true> InstX8632Psub;
typedef InstX8632BinopGPR<InstX8632::And> InstX8632And; typedef InstX8632BinopGPR<InstX8632::And> InstX8632And;
typedef InstX8632BinopRMW<InstX8632::AndRMW> InstX8632AndRMW;
typedef InstX8632BinopXmm<InstX8632::Pand, false> InstX8632Pand; typedef InstX8632BinopXmm<InstX8632::Pand, false> InstX8632Pand;
typedef InstX8632BinopXmm<InstX8632::Pandn, false> InstX8632Pandn; typedef InstX8632BinopXmm<InstX8632::Pandn, false> InstX8632Pandn;
typedef InstX8632BinopGPR<InstX8632::Or> InstX8632Or; typedef InstX8632BinopGPR<InstX8632::Or> InstX8632Or;
typedef InstX8632BinopRMW<InstX8632::OrRMW> InstX8632OrRMW;
typedef InstX8632BinopXmm<InstX8632::Por, false> InstX8632Por; typedef InstX8632BinopXmm<InstX8632::Por, false> InstX8632Por;
typedef InstX8632BinopGPR<InstX8632::Xor> InstX8632Xor; typedef InstX8632BinopGPR<InstX8632::Xor> InstX8632Xor;
typedef InstX8632BinopRMW<InstX8632::XorRMW> InstX8632XorRMW;
typedef InstX8632BinopXmm<InstX8632::Pxor, false> InstX8632Pxor; typedef InstX8632BinopXmm<InstX8632::Pxor, false> InstX8632Pxor;
typedef InstX8632BinopGPR<InstX8632::Imul> InstX8632Imul; typedef InstX8632BinopGPR<InstX8632::Imul> InstX8632Imul;
typedef InstX8632BinopXmm<InstX8632::Mulps, true> InstX8632Mulps; typedef InstX8632BinopXmm<InstX8632::Mulps, true> InstX8632Mulps;
......
...@@ -517,8 +517,9 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var, ...@@ -517,8 +517,9 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
for (VariableDeclaration::Initializer *Init : Var.getInitializers()) { for (VariableDeclaration::Initializer *Init : Var.getInitializers()) {
switch (Init->getKind()) { switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: { case VariableDeclaration::Initializer::DataInitializerKind: {
const auto &Data = llvm::cast<VariableDeclaration::DataInitializer>( const auto &Data =
Init)->getContents(); llvm::cast<VariableDeclaration::DataInitializer>(Init)
->getContents();
for (SizeT i = 0; i < Init->getNumBytes(); ++i) { for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
} }
......
...@@ -587,32 +587,31 @@ namespace { ...@@ -587,32 +587,31 @@ namespace {
bool canRMW(const InstArithmetic *Arith) { bool canRMW(const InstArithmetic *Arith) {
Type Ty = Arith->getDest()->getType(); Type Ty = Arith->getDest()->getType();
// X86 vector instructions write to a register and have no RMW
// option.
if (isVectorType(Ty))
return false;
bool isI64 = Ty == IceType_i64; bool isI64 = Ty == IceType_i64;
bool isVector = isVectorType(Ty);
switch (Arith->getOp()) { switch (Arith->getOp()) {
// Not handled for lack of simple lowering: // Not handled for lack of simple lowering:
// shift on i64 and vectors // shift on i64
// mul, udiv, urem, sdiv, srem, frem // mul, udiv, urem, sdiv, srem, frem
// Not handled for lack of RMW instructions:
// fadd, fsub, fmul, fdiv (also vector types)
default: default:
return false; return false;
case InstArithmetic::Add: case InstArithmetic::Add:
return !isI64 && !isVector; // TODO(stichnot): implement i64 and vector
case InstArithmetic::Sub: case InstArithmetic::Sub:
case InstArithmetic::And: case InstArithmetic::And:
case InstArithmetic::Or: case InstArithmetic::Or:
case InstArithmetic::Xor: case InstArithmetic::Xor:
case InstArithmetic::Fadd:
case InstArithmetic::Fsub:
case InstArithmetic::Fmul:
case InstArithmetic::Fdiv:
return false; // TODO(stichnot): implement
return true; return true;
case InstArithmetic::Shl: case InstArithmetic::Shl:
case InstArithmetic::Lshr: case InstArithmetic::Lshr:
case InstArithmetic::Ashr: case InstArithmetic::Ashr:
return false; // TODO(stichnot): implement return false; // TODO(stichnot): implement
return !isI64 && !isVector; return !isI64;
} }
} }
...@@ -3442,9 +3441,10 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { ...@@ -3442,9 +3441,10 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
Func->setError("Unexpected memory ordering for AtomicRMW"); Func->setError("Unexpected memory ordering for AtomicRMW");
return; return;
} }
lowerAtomicRMW(Instr->getDest(), lowerAtomicRMW(
static_cast<uint32_t>(llvm::cast<ConstantInteger32>( Instr->getDest(),
Instr->getArg(0))->getValue()), static_cast<uint32_t>(
llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()),
Instr->getArg(1), Instr->getArg(2)); Instr->getArg(1), Instr->getArg(2));
return; return;
case Intrinsics::AtomicStore: { case Intrinsics::AtomicStore: {
...@@ -4660,11 +4660,37 @@ void TargetX8632::lowerRMW(const InstX8632FakeRMW *RMW) { ...@@ -4660,11 +4660,37 @@ void TargetX8632::lowerRMW(const InstX8632FakeRMW *RMW) {
Type Ty = Src->getType(); Type Ty = Src->getType();
OperandX8632Mem *Addr = formMemoryOperand(RMW->getAddr(), Ty); OperandX8632Mem *Addr = formMemoryOperand(RMW->getAddr(), Ty);
if (Ty == IceType_i64) { if (Ty == IceType_i64) {
// TODO(stichnot): Implement. Operand *SrcLo = legalize(loOperand(Src), Legal_Reg | Legal_Imm);
} else if (isVectorType(Ty)) { Operand *SrcHi = legalize(hiOperand(Src), Legal_Reg | Legal_Imm);
// TODO(stichnot): Implement. OperandX8632Mem *AddrLo = llvm::cast<OperandX8632Mem>(loOperand(Addr));
OperandX8632Mem *AddrHi = llvm::cast<OperandX8632Mem>(hiOperand(Addr));
switch (RMW->getOp()) {
default:
// TODO(stichnot): Implement other arithmetic operators.
break;
case InstArithmetic::Add:
_add_rmw(AddrLo, SrcLo);
_adc_rmw(AddrHi, SrcHi);
return;
case InstArithmetic::Sub:
_sub_rmw(AddrLo, SrcLo);
_sbb_rmw(AddrHi, SrcHi);
return;
case InstArithmetic::And:
_and_rmw(AddrLo, SrcLo);
_and_rmw(AddrHi, SrcHi);
return;
case InstArithmetic::Or:
_or_rmw(AddrLo, SrcLo);
_or_rmw(AddrHi, SrcHi);
return;
case InstArithmetic::Xor:
_xor_rmw(AddrLo, SrcLo);
_xor_rmw(AddrHi, SrcHi);
return;
}
} else { } else {
// i8, i16, i32, f32, f64 // i8, i16, i32
switch (RMW->getOp()) { switch (RMW->getOp()) {
default: default:
// TODO(stichnot): Implement other arithmetic operators. // TODO(stichnot): Implement other arithmetic operators.
...@@ -4673,6 +4699,22 @@ void TargetX8632::lowerRMW(const InstX8632FakeRMW *RMW) { ...@@ -4673,6 +4699,22 @@ void TargetX8632::lowerRMW(const InstX8632FakeRMW *RMW) {
Src = legalize(Src, Legal_Reg | Legal_Imm); Src = legalize(Src, Legal_Reg | Legal_Imm);
_add_rmw(Addr, Src); _add_rmw(Addr, Src);
return; return;
case InstArithmetic::Sub:
Src = legalize(Src, Legal_Reg | Legal_Imm);
_sub_rmw(Addr, Src);
return;
case InstArithmetic::And:
Src = legalize(Src, Legal_Reg | Legal_Imm);
_and_rmw(Addr, Src);
return;
case InstArithmetic::Or:
Src = legalize(Src, Legal_Reg | Legal_Imm);
_or_rmw(Addr, Src);
return;
case InstArithmetic::Xor:
Src = legalize(Src, Legal_Reg | Legal_Imm);
_xor_rmw(Addr, Src);
return;
} }
} }
llvm::report_fatal_error("Couldn't lower RMW instruction"); llvm::report_fatal_error("Couldn't lower RMW instruction");
......
...@@ -264,6 +264,9 @@ protected: ...@@ -264,6 +264,9 @@ protected:
void _adc(Variable *Dest, Operand *Src0) { void _adc(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Adc::create(Func, Dest, Src0)); Context.insert(InstX8632Adc::create(Func, Dest, Src0));
} }
void _adc_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632AdcRMW::create(Func, DestSrc0, Src1));
}
void _add(Variable *Dest, Operand *Src0) { void _add(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Add::create(Func, Dest, Src0)); Context.insert(InstX8632Add::create(Func, Dest, Src0));
} }
...@@ -283,6 +286,9 @@ protected: ...@@ -283,6 +286,9 @@ protected:
void _and(Variable *Dest, Operand *Src0) { void _and(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632And::create(Func, Dest, Src0)); Context.insert(InstX8632And::create(Func, Dest, Src0));
} }
void _and_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632AndRMW::create(Func, DestSrc0, Src1));
}
void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) { void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1)); Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1));
} }
...@@ -425,6 +431,9 @@ protected: ...@@ -425,6 +431,9 @@ protected:
void _or(Variable *Dest, Operand *Src0) { void _or(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Or::create(Func, Dest, Src0)); Context.insert(InstX8632Or::create(Func, Dest, Src0));
} }
void _or_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632OrRMW::create(Func, DestSrc0, Src1));
}
void _padd(Variable *Dest, Operand *Src0) { void _padd(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Padd::create(Func, Dest, Src0)); Context.insert(InstX8632Padd::create(Func, Dest, Src0));
} }
...@@ -494,6 +503,9 @@ protected: ...@@ -494,6 +503,9 @@ protected:
void _sbb(Variable *Dest, Operand *Src0) { void _sbb(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Sbb::create(Func, Dest, Src0)); Context.insert(InstX8632Sbb::create(Func, Dest, Src0));
} }
void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632SbbRMW::create(Func, DestSrc0, Src1));
}
void _setcc(Variable *Dest, CondX86::BrCond Condition) { void _setcc(Variable *Dest, CondX86::BrCond Condition) {
Context.insert(InstX8632Setcc::create(Func, Dest, Condition)); Context.insert(InstX8632Setcc::create(Func, Dest, Condition));
} }
...@@ -527,6 +539,9 @@ protected: ...@@ -527,6 +539,9 @@ protected:
void _sub(Variable *Dest, Operand *Src0) { void _sub(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Sub::create(Func, Dest, Src0)); Context.insert(InstX8632Sub::create(Func, Dest, Src0));
} }
void _sub_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632SubRMW::create(Func, DestSrc0, Src1));
}
void _subps(Variable *Dest, Operand *Src0) { void _subps(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Subps::create(Func, Dest, Src0)); Context.insert(InstX8632Subps::create(Func, Dest, Src0));
} }
...@@ -561,6 +576,9 @@ protected: ...@@ -561,6 +576,9 @@ protected:
void _xor(Variable *Dest, Operand *Src0) { void _xor(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Xor::create(Func, Dest, Src0)); Context.insert(InstX8632Xor::create(Func, Dest, Src0));
} }
void _xor_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632XorRMW::create(Func, DestSrc0, Src1));
}
void _set_dest_nonkillable() { void _set_dest_nonkillable() {
Context.getLastInserted()->setDestNonKillable(); Context.getLastInserted()->setDestNonKillable();
} }
......
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