Commit 2758bb07 by John Porto

Subzero. ARM32. Introduces the ShAmtImm Operand.

Creates a special OperandARM32 for representing imm5 used when performing a shift operation. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=kschimpf@google.com Review URL: https://codereview.chromium.org/1449263003 .
parent cdb3ed68
...@@ -247,6 +247,9 @@ OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, ...@@ -247,6 +247,9 @@ OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
Vars[1] = Index; Vars[1] = Index;
} }
OperandARM32ShAmtImm::OperandARM32ShAmtImm(ConstantInteger32 *SA)
: OperandARM32(kShAmtImm, IceType_i8), ShAmt(SA) {}
bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) { bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
: TypeARM32Attributes[Ty].ZExtAddrOffsetBits; : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
...@@ -1771,6 +1774,12 @@ void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const { ...@@ -1771,6 +1774,12 @@ void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
Str << "] AddrMode==" << getAddrMode(); Str << "] AddrMode==" << getAddrMode();
} }
void OperandARM32ShAmtImm::emit(const Cfg *Func) const { ShAmt->emit(Func); }
void OperandARM32ShAmtImm::dump(const Cfg *, Ostream &Str) const {
ShAmt->dump(Str);
}
void OperandARM32FlexImm::emit(const Cfg *Func) const { void OperandARM32FlexImm::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -38,6 +38,7 @@ public: ...@@ -38,6 +38,7 @@ public:
enum OperandKindARM32 { enum OperandKindARM32 {
k__Start = Operand::kTarget, k__Start = Operand::kTarget,
kMem, kMem,
kShAmtImm,
kFlexStart, kFlexStart,
kFlexImm = kFlexStart, kFlexImm = kFlexStart,
kFlexFpImm, kFlexFpImm,
...@@ -152,6 +153,36 @@ private: ...@@ -152,6 +153,36 @@ private:
AddrMode Mode; AddrMode Mode;
}; };
/// OperandARM32ShAmtImm represents an Immediate that is used in one of the
/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
/// shifted registers.
class OperandARM32ShAmtImm : public OperandARM32 {
OperandARM32ShAmtImm() = delete;
OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;
public:
static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
return new (Func->allocate<OperandARM32ShAmtImm>())
OperandARM32ShAmtImm(ShAmt);
}
static bool classof(const Operand *Operand) {
return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
}
void emit(const Cfg *Func) const override;
using OperandARM32::dump;
void dump(const Cfg *Func, Ostream &Str) const override;
uint32_t getShAmtImm() const { return ShAmt->getValue(); }
private:
explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);
const ConstantInteger32 *const ShAmt;
};
/// OperandARM32Flex represent the "flexible second operand" for data-processing /// OperandARM32Flex represent the "flexible second operand" for data-processing
/// instructions. It can be a rotatable 8-bit constant, or a register with an /// instructions. It can be a rotatable 8-bit constant, or a register with an
/// optional shift operand. The shift amount can even be a third register. /// optional shift operand. The shift amount can even be a third register.
......
...@@ -1300,11 +1300,9 @@ void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { ...@@ -1300,11 +1300,9 @@ void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) {
llvm::report_fatal_error("Unexpected type"); llvm::report_fatal_error("Unexpected type");
case IceType_i8: case IceType_i8:
case IceType_i16: { case IceType_i16: {
Operand *ShAmtF = Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty));
legalize(Ctx->getConstantInt32(32 - getScalarIntBitWidth(Ty)),
Legal_Reg | Legal_Flex);
Variable *T = makeReg(IceType_i32); Variable *T = makeReg(IceType_i32);
_lsls(T, SrcLoReg, ShAmtF); _lsls(T, SrcLoReg, ShAmtImm);
Context.insert(InstFakeUse::create(Func, T)); Context.insert(InstFakeUse::create(Func, T));
} break; } break;
case IceType_i32: { case IceType_i32: {
...@@ -1454,10 +1452,6 @@ public: ...@@ -1454,10 +1452,6 @@ public:
return legalizeToReg(Target, Swapped ? Src0 : Src1); return legalizeToReg(Target, Swapped ? Src0 : Src1);
} }
Operand *unswappedSrc1RF(TargetARM32 *Target) const {
return legalizeToRegOrFlex(Target, Swapped ? Src0 : Src1);
}
protected: protected:
Operand *const Src0; Operand *const Src0;
Operand *const Src1; Operand *const Src1;
...@@ -1522,6 +1516,13 @@ class Int32Operands : public NumericOperands<ConstantInteger32> { ...@@ -1522,6 +1516,13 @@ class Int32Operands : public NumericOperands<ConstantInteger32> {
public: public:
Int32Operands(Operand *S0, Operand *S1) : NumericOperands(S0, S1) {} Int32Operands(Operand *S0, Operand *S1) : NumericOperands(S0, S1) {}
Operand *unswappedSrc1RShAmtImm(TargetARM32 *Target) const {
if (!swappedOperands() && hasConstOperand()) {
return Target->shAmtImm(getConstantValue() & 0x1F);
}
return legalizeToReg(Target, Swapped ? Src0 : Src1);
}
bool immediateIsFlexEncodable() const { bool immediateIsFlexEncodable() const {
uint32_t Rotate, Imm8; uint32_t Rotate, Imm8;
return OperandARM32FlexImm::canHoldImm(getConstantValue(), &Rotate, &Imm8); return OperandARM32FlexImm::canHoldImm(getConstantValue(), &Rotate, &Imm8);
...@@ -1738,8 +1739,7 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, ...@@ -1738,8 +1739,7 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
if (ShAmtImm == 32) { if (ShAmtImm == 32) {
_mov(DestHi, Src0RLo); _mov(DestHi, Src0RLo);
} else { } else {
Operand *ShAmtOp = legalize(Ctx->getConstantInt32(ShAmtImm - 32), Operand *ShAmtOp = shAmtImm(ShAmtImm - 32);
Legal_Reg | Legal_Flex);
_lsl(T_Hi, Src0RLo, ShAmtOp); _lsl(T_Hi, Src0RLo, ShAmtOp);
_mov(DestHi, T_Hi); _mov(DestHi, T_Hi);
} }
...@@ -1752,10 +1752,8 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, ...@@ -1752,10 +1752,8 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
} }
Variable *Src0RHi = SrcsHi.src0R(this); Variable *Src0RHi = SrcsHi.src0R(this);
Operand *ShAmtOp = Operand *ShAmtOp = shAmtImm(ShAmtImm);
legalize(Ctx->getConstantInt32(ShAmtImm), Legal_Reg | Legal_Flex); Operand *ComplShAmtOp = shAmtImm(32 - ShAmtImm);
Operand *ComplShAmtOp = legalize(Ctx->getConstantInt32(32 - ShAmtImm),
Legal_Reg | Legal_Flex);
_lsl(T_Hi, Src0RHi, ShAmtOp); _lsl(T_Hi, Src0RHi, ShAmtOp);
_orr(T_Hi, T_Hi, _orr(T_Hi, T_Hi,
OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
...@@ -1828,30 +1826,28 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, ...@@ -1828,30 +1826,28 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) { if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) {
Variable *Src0RHi = SrcsHi.src0R(this); Variable *Src0RHi = SrcsHi.src0R(this);
// Truncating the ShAmt to [0, 63] because that's what ARM does anyway. // Truncating the ShAmt to [0, 63] because that's what ARM does anyway.
const int32_t ShAmtImm = SrcsLo.getConstantValue() & 0x3F; const int32_t ShAmt = SrcsLo.getConstantValue() & 0x3F;
if (ShAmtImm == 0) { if (ShAmt == 0) {
_mov(DestHi, Src0RHi); _mov(DestHi, Src0RHi);
_mov(DestLo, SrcsLo.src0R(this)); _mov(DestLo, SrcsLo.src0R(this));
return; return;
} }
if (ShAmtImm >= 32) { if (ShAmt >= 32) {
if (ShAmtImm == 32) { if (ShAmt == 32) {
_mov(DestLo, Src0RHi); _mov(DestLo, Src0RHi);
} else { } else {
Operand *ShAmtOp = legalize(Ctx->getConstantInt32(ShAmtImm - 32), Operand *ShAmtImm = shAmtImm(ShAmt - 32);
Legal_Reg | Legal_Flex);
if (ASR) { if (ASR) {
_asr(T_Lo, Src0RHi, ShAmtOp); _asr(T_Lo, Src0RHi, ShAmtImm);
} else { } else {
_lsr(T_Lo, Src0RHi, ShAmtOp); _lsr(T_Lo, Src0RHi, ShAmtImm);
} }
_mov(DestLo, T_Lo); _mov(DestLo, T_Lo);
} }
if (ASR) { if (ASR) {
Operand *_31 = legalize(Ctx->getConstantZero(IceType_i32), Operand *_31 = shAmtImm(31);
Legal_Reg | Legal_Flex);
_asr(T_Hi, Src0RHi, _31); _asr(T_Hi, Src0RHi, _31);
} else { } else {
Operand *_0 = legalize(Ctx->getConstantZero(IceType_i32), Operand *_0 = legalize(Ctx->getConstantZero(IceType_i32),
...@@ -1863,20 +1859,18 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, ...@@ -1863,20 +1859,18 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
} }
Variable *Src0RLo = SrcsLo.src0R(this); Variable *Src0RLo = SrcsLo.src0R(this);
Operand *ShAmtOp = Operand *ShAmtImm = shAmtImm(ShAmt);
legalize(Ctx->getConstantInt32(ShAmtImm), Legal_Reg | Legal_Flex); Operand *ComplShAmtImm = shAmtImm(32 - ShAmt);
Operand *ComplShAmtOp = legalize(Ctx->getConstantInt32(32 - ShAmtImm), _lsr(T_Lo, Src0RLo, ShAmtImm);
Legal_Reg | Legal_Flex);
_lsr(T_Lo, Src0RLo, ShAmtOp);
_orr(T_Lo, T_Lo, _orr(T_Lo, T_Lo,
OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
OperandARM32::LSL, ComplShAmtOp)); OperandARM32::LSL, ComplShAmtImm));
_mov(DestLo, T_Lo); _mov(DestLo, T_Lo);
if (ASR) { if (ASR) {
_asr(T_Hi, Src0RHi, ShAmtOp); _asr(T_Hi, Src0RHi, ShAmtImm);
} else { } else {
_lsr(T_Hi, Src0RHi, ShAmtOp); _lsr(T_Hi, Src0RHi, ShAmtImm);
} }
_mov(DestHi, T_Hi); _mov(DestHi, T_Hi);
return; return;
...@@ -2151,7 +2145,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -2151,7 +2145,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
} }
case InstArithmetic::Shl: { case InstArithmetic::Shl: {
Variable *Src0R = Srcs.unswappedSrc0R(this); Variable *Src0R = Srcs.unswappedSrc0R(this);
Operand *Src1R = Srcs.unswappedSrc1RF(this); Operand *Src1R = Srcs.unswappedSrc1RShAmtImm(this);
_lsl(T, Src0R, Src1R); _lsl(T, Src0R, Src1R);
_mov(Dest, T); _mov(Dest, T);
return; return;
...@@ -2161,7 +2155,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -2161,7 +2155,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
if (Dest->getType() != IceType_i32) { if (Dest->getType() != IceType_i32) {
_uxt(Src0R, Src0R); _uxt(Src0R, Src0R);
} }
_lsr(T, Src0R, Srcs.unswappedSrc1RF(this)); _lsr(T, Src0R, Srcs.unswappedSrc1RShAmtImm(this));
_mov(Dest, T); _mov(Dest, T);
return; return;
} }
...@@ -2170,7 +2164,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -2170,7 +2164,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
if (Dest->getType() != IceType_i32) { if (Dest->getType() != IceType_i32) {
_sxt(Src0R, Src0R); _sxt(Src0R, Src0R);
} }
_asr(T, Src0R, Srcs.unswappedSrc1RF(this)); _asr(T, Src0R, Srcs.unswappedSrc1RShAmtImm(this));
_mov(Dest, T); _mov(Dest, T);
return; return;
} }
...@@ -3185,22 +3179,21 @@ TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0, ...@@ -3185,22 +3179,21 @@ TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
if (!Srcs.hasConstOperand()) { if (!Srcs.hasConstOperand()) {
Variable *Src0R = makeReg(IceType_i32); Variable *Src0R = makeReg(IceType_i32);
Operand *ShAmtF = Operand *ShAmtImm = shAmtImm(ShAmt);
legalize(Ctx->getConstantInt32(ShAmt), Legal_Reg | Legal_Flex); _lsl(Src0R, legalizeToReg(Src0), ShAmtImm);
_lsl(Src0R, legalizeToReg(Src0), ShAmtF);
Variable *Src1R = legalizeToReg(Src1); Variable *Src1R = legalizeToReg(Src1);
OperandARM32FlexReg *Src1F = OperandARM32FlexReg::create( OperandARM32FlexReg *Src1F = OperandARM32FlexReg::create(
Func, IceType_i32, Src1R, OperandARM32::LSL, ShAmtF); Func, IceType_i32, Src1R, OperandARM32::LSL, ShAmtImm);
_cmp(Src0R, Src1F); _cmp(Src0R, Src1F);
return CondWhenTrue(getIcmp32Mapping(Condition)); return CondWhenTrue(getIcmp32Mapping(Condition));
} }
const int32_t Value = Srcs.getConstantValue(); const int32_t Value = Srcs.getConstantValue();
if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) { if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) {
Operand *ShAmtOp = Ctx->getConstantInt32(ShAmt); Operand *ShAmtImm = shAmtImm(ShAmt);
Variable *T = makeReg(IceType_i32); Variable *T = makeReg(IceType_i32);
_lsls(T, Srcs.src0R(this), ShAmtOp); _lsls(T, Srcs.src0R(this), ShAmtImm);
Context.insert(InstFakeUse::create(Func, T)); Context.insert(InstFakeUse::create(Func, T));
return CondWhenTrue(getIcmp32Mapping(Condition)); return CondWhenTrue(getIcmp32Mapping(Condition));
} }
...@@ -3777,9 +3770,8 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { ...@@ -3777,9 +3770,8 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
Variable *T = makeReg(Ty); Variable *T = makeReg(Ty);
_rev(T, ValR); _rev(T, ValR);
if (Val->getType() == IceType_i16) { if (Val->getType() == IceType_i16) {
Operand *Sixteen = Operand *_16 = shAmtImm(16);
legalize(Ctx->getConstantInt32(16), Legal_Reg | Legal_Flex); _lsr(T, T, _16);
_lsr(T, T, Sixteen);
} }
_mov(Dest, T); _mov(Dest, T);
} }
...@@ -4573,9 +4565,9 @@ void TargetARM32::lowerSwitch(const InstSwitch *Inst) { ...@@ -4573,9 +4565,9 @@ void TargetARM32::lowerSwitch(const InstSwitch *Inst) {
const size_t ShiftAmt = 32 - getScalarIntBitWidth(Src0->getType()); const size_t ShiftAmt = 32 - getScalarIntBitWidth(Src0->getType());
assert(ShiftAmt < 32); assert(ShiftAmt < 32);
if (ShiftAmt > 0) { if (ShiftAmt > 0) {
Operand *ShiftConst = Ctx->getConstantInt32(ShiftAmt); Operand *ShAmtImm = shAmtImm(ShiftAmt);
Variable *T = makeReg(IceType_i32); Variable *T = makeReg(IceType_i32);
_lsl(T, Src0Var, ShiftConst); _lsl(T, Src0Var, ShAmtImm);
Src0Var = T; Src0Var = T;
} }
......
...@@ -156,6 +156,13 @@ public: ...@@ -156,6 +156,13 @@ public:
int32_t RegNum = Variable::NoRegister); int32_t RegNum = Variable::NoRegister);
Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
assert(ShAmtImm < 32);
return OperandARM32ShAmtImm::create(
Func,
llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F)));
}
GlobalContext *getCtx() const { return Ctx; } GlobalContext *getCtx() const { return Ctx; }
protected: protected:
......
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