Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Unified Diff: src/IceTargetLoweringARM32.cpp

Issue 1359193003: Subzero. Enables (most) crosstests for ARM32. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringARM32.cpp
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index d61d93cf0430b57ff316dd2ab95ce07b48f33acf..f92160b47f0b7eb9ee3516f598bf24edb6b4b157 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -20,6 +20,7 @@
#include "IceDefs.h"
#include "IceELFObjectWriter.h"
#include "IceGlobalInits.h"
+#include "IceInstARM32.def"
#include "IceInstARM32.h"
#include "IceLiveness.h"
#include "IceOperand.h"
@@ -30,6 +31,7 @@
#include "llvm/Support/MathExtras.h"
#include <algorithm>
+#include <utility>
namespace Ice {
@@ -380,8 +382,21 @@ IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const {
}
Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) {
- if (Ty == IceType_void)
- Ty = IceType_i32;
+ static const Type DefaultType[] = {
+#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
+ isFP32, isFP64, isVec128, alias_init) \
+ (isFP32) \
+ ? IceType_f32 \
+ : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))),
+ REGARM32_TABLE
+#undef X
+ };
+
+ assert(RegNum < RegARM32::Reg_NUM);
+ if (Ty == IceType_void) {
+ assert(RegNum < llvm::array_lengthof(DefaultType));
+ Ty = DefaultType[RegNum];
+ }
if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM);
assert(RegNum < PhysicalRegisters[Ty].size());
@@ -425,11 +440,17 @@ void TargetARM32::emitVariable(const Variable *Var) const {
if (!hasFramePointer())
Offset += getStackAdjustment();
}
- if (!isLegalVariableStackOffset(Offset)) {
+ const Type VarTy = Var->getType();
+ // In general, no Variable64On32 should be emited in textual asm output. It
+ // turns out that some lowering sequences Fake-Def/Fake-Use such a variables.
+ // If they end up being assigned an illegal offset we get a runtime error. We
+ // liberally allow Variable64On32 to have illegal offsets because offsets
+ // don't matter in FakeDefs/FakeUses.
+ if (!llvm::isa<Variable64On32>(Var) &&
+ !isLegalVariableStackOffset(VarTy, Offset)) {
llvm::report_fatal_error("Illegal stack offset");
}
- const Type FrameSPTy = stackSlotType();
- Str << "[" << getRegName(BaseRegNum, FrameSPTy);
+ Str << "[" << getRegName(BaseRegNum, VarTy);
if (Offset != 0) {
Str << ", " << getConstantPrefix() << Offset;
}
@@ -592,17 +613,14 @@ void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
// value from the stack slot.
if (Arg->hasReg()) {
assert(Ty != IceType_i64);
- OperandARM32Mem *Mem = OperandARM32Mem::create(
+ // This should be simple, just load the parameter off the stack using a nice
+ // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for
+ // fp types, cannot have an index register), so we legalize the memory
+ // operand instead.
+ auto *Mem = OperandARM32Mem::create(
Func, Ty, FramePtr, llvm::cast<ConstantInteger32>(
Ctx->getConstantInt32(Arg->getStackOffset())));
- if (isVectorType(Arg->getType())) {
- // Use vld1.$elem or something?
- UnimplementedError(Func->getContext()->getFlags());
- } else if (isFloatingType(Arg->getType())) {
- _vldr(Arg, Mem);
- } else {
- _ldr(Arg, Mem);
- }
+ legalizeToReg(Mem, Arg->getRegNum());
// This argument-copying instruction uses an explicit OperandARM32Mem
// operand instead of a Variable, so its fill-from-stack operation has to
// be tracked separately for statistics.
@@ -894,16 +912,15 @@ void TargetARM32::addEpilog(CfgNode *Node) {
RI->setDeleted();
}
-bool TargetARM32::isLegalVariableStackOffset(int32_t Offset) const {
+bool TargetARM32::isLegalVariableStackOffset(Type Ty, int32_t Offset) const {
constexpr bool SignExt = false;
- // TODO(jvoung): vldr of FP stack slots has a different limit from the plain
- // stackSlotType().
- return OperandARM32Mem::canHoldOffset(stackSlotType(), SignExt, Offset);
+ return OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset);
}
StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var,
+ int32_t StackAdjust,
Variable *OrigBaseReg) {
- int32_t Offset = Var->getStackOffset();
+ int32_t Offset = Var->getStackOffset() + StackAdjust;
// Legalize will likely need a movw/movt combination, but if the top bits are
// all 0 from negating the offset and subtracting, we could use that instead.
bool ShouldSub = (-Offset & 0xFFFF0000) == 0;
@@ -937,7 +954,9 @@ void TargetARM32::legalizeStackSlots() {
Func->dump("Before legalizeStackSlots");
assert(hasComputedFrame());
// Early exit, if SpillAreaSizeBytes is really small.
- if (isLegalVariableStackOffset(SpillAreaSizeBytes))
+ // TODO(jpp): this is not safe -- loads and stores of q registers can't have
+ // offsets.
+ if (isLegalVariableStackOffset(IceType_v4i32, SpillAreaSizeBytes))
return;
Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg());
int32_t StackAdjust = 0;
@@ -978,64 +997,77 @@ void TargetARM32::legalizeStackSlots() {
continue;
}
}
+
// For now, only Mov instructions can have stack variables. We need to
// know the type of instruction because we currently create a fresh one
// to replace Dest/Source, rather than mutate in place.
- auto *MovInst = llvm::dyn_cast<InstARM32Mov>(CurInstr);
- if (!MovInst) {
+ bool MayNeedOffsetRewrite = false;
+ if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
+ MayNeedOffsetRewrite =
+ !MovInstr->isMultiDest() && !MovInstr->isMultiSource();
+ }
+
+ if (!MayNeedOffsetRewrite) {
continue;
}
+
+ assert(Dest != nullptr);
+ Type DestTy = Dest->getType();
+ assert(DestTy != IceType_i64);
if (!Dest->hasReg()) {
int32_t Offset = Dest->getStackOffset();
Offset += StackAdjust;
- if (!isLegalVariableStackOffset(Offset)) {
+ if (!isLegalVariableStackOffset(DestTy, Offset)) {
if (NewBaseReg) {
int32_t OffsetDiff = Offset - NewBaseOffset;
- if (isLegalVariableStackOffset(OffsetDiff)) {
+ if (isLegalVariableStackOffset(DestTy, OffsetDiff)) {
StackVariable *NewDest =
Func->makeVariable<StackVariable>(stackSlotType());
NewDest->setMustNotHaveReg();
NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum());
NewDest->setStackOffset(OffsetDiff);
Variable *NewDestVar = NewDest;
- _mov(NewDestVar, MovInst->getSrc(0));
- MovInst->setDeleted();
+ _mov(NewDestVar, CurInstr->getSrc(0));
+ CurInstr->setDeleted();
continue;
}
}
- StackVariable *LegalDest = legalizeVariableSlot(Dest, OrigBaseReg);
+ StackVariable *LegalDest =
+ legalizeVariableSlot(Dest, StackAdjust, OrigBaseReg);
assert(LegalDest != Dest);
Variable *LegalDestVar = LegalDest;
- _mov(LegalDestVar, MovInst->getSrc(0));
- MovInst->setDeleted();
+ _mov(LegalDestVar, CurInstr->getSrc(0));
+ CurInstr->setDeleted();
NewBaseReg = LegalDest;
NewBaseOffset = Offset;
continue;
}
}
- assert(MovInst->getSrcSize() == 1);
- Variable *Var = llvm::dyn_cast<Variable>(MovInst->getSrc(0));
+ assert(CurInstr->getSrcSize() == 1);
+ Variable *Var = llvm::dyn_cast<Variable>(CurInstr->getSrc(0));
if (Var && !Var->hasReg()) {
+ Type VarTy = Var->getType();
int32_t Offset = Var->getStackOffset();
Offset += StackAdjust;
- if (!isLegalVariableStackOffset(Offset)) {
+ if (!isLegalVariableStackOffset(VarTy, Offset)) {
if (NewBaseReg) {
int32_t OffsetDiff = Offset - NewBaseOffset;
- if (isLegalVariableStackOffset(OffsetDiff)) {
+ if (isLegalVariableStackOffset(VarTy, OffsetDiff)) {
StackVariable *NewVar =
Func->makeVariable<StackVariable>(stackSlotType());
NewVar->setMustNotHaveReg();
NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum());
NewVar->setStackOffset(OffsetDiff);
_mov(Dest, NewVar);
- MovInst->setDeleted();
+ CurInstr->setDeleted();
continue;
}
}
- StackVariable *LegalVar = legalizeVariableSlot(Var, OrigBaseReg);
+ StackVariable *LegalVar =
+ legalizeVariableSlot(Var, StackAdjust, OrigBaseReg);
assert(LegalVar != Var);
_mov(Dest, LegalVar);
- MovInst->setDeleted();
+ CurInstr->setDeleted();
NewBaseReg = LegalVar;
NewBaseOffset = Offset;
continue;
@@ -1427,6 +1459,20 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
}
case InstArithmetic::Shl: {
// a=b<<c ==>
+ // pnacl-llc does:
+ // mov t_b.lo, b.lo
+ // mov t_b.hi, b.hi
+ // mov t_c.lo, c.lo
+ // rsb T0, t_c.lo, #32
+ // lsr T1, t_b.lo, T0
+ // orr t_a.hi, T1, t_b.hi, lsl t_c.lo
+ // sub T2, t_c.lo, #32
+ // cmp T2, #0
+ // lslge t_a.hi, t_b.lo, T2
+ // lsl t_a.lo, t_b.lo, t_c.lo
+ // mov a.lo, t_a.lo
+ // mov a.hi, t_a.hi
+ //
// GCC 4.8 does:
// sub t_c1, c.lo, #32
// lsl t_hi, b.hi, c.lo
@@ -1436,78 +1482,88 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
// lsl t_lo, b.lo, c.lo
// a.lo = t_lo
// a.hi = t_hi
+ //
+ // These are incompatible, therefore we mimic pnacl-llc.
// Can be strength-reduced for constant-shifts, but we don't do that for
// now.
// Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On
// ARM, shifts only take the lower 8 bits of the shift register, and
// saturate to the range 0-32, so the negative value will saturate to 32.
- Variable *T_Hi = makeReg(IceType_i32);
+ Constant *_32 = Ctx->getConstantInt32(32);
+ Constant *_0 = Ctx->getConstantZero(IceType_i32);
Variable *Src1RLo = legalizeToReg(Src1Lo);
- Constant *ThirtyTwo = Ctx->getConstantInt32(32);
- Variable *T_C1 = makeReg(IceType_i32);
- Variable *T_C2 = makeReg(IceType_i32);
- _sub(T_C1, Src1RLo, ThirtyTwo);
- _lsl(T_Hi, Src0RHi, Src1RLo);
- _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
- OperandARM32::LSL, T_C1));
- _rsb(T_C2, Src1RLo, ThirtyTwo);
- _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
- OperandARM32::LSR, T_C2));
- _mov(DestHi, T_Hi);
- Variable *T_Lo = makeReg(IceType_i32);
- // _mov seems to sometimes have better register preferencing than lsl.
- // Otherwise mov w/ lsl shifted register is a pseudo-instruction that
- // maps to lsl.
- _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
- OperandARM32::LSL, Src1RLo));
- _mov(DestLo, T_Lo);
+ Variable *T0 = makeReg(IceType_i32);
+ Variable *T1 = makeReg(IceType_i32);
+ Variable *T2 = makeReg(IceType_i32);
+ Variable *TA_Hi = makeReg(IceType_i32);
+ Variable *TA_Lo = makeReg(IceType_i32);
+ _rsb(T0, Src1RLo, _32);
+ _lsr(T1, Src0RLo, T0);
+ _orr(TA_Hi, T1, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
+ OperandARM32::LSL, Src1RLo));
+ _sub(T2, Src1RLo, _32);
+ _cmp(T2, _0);
+ _lsl(TA_Hi, Src0RLo, T2, CondARM32::GE);
+ _set_dest_nonkillable();
+ _lsl(TA_Lo, Src0RLo, Src1RLo);
+ _mov(DestLo, TA_Lo);
+ _mov(DestHi, TA_Hi);
return;
}
case InstArithmetic::Lshr:
- // a=b>>c (unsigned) ==>
- // GCC 4.8 does:
- // rsb t_c1, c.lo, #32
- // lsr t_lo, b.lo, c.lo
- // orr t_lo, t_lo, b.hi, lsl t_c1
- // sub t_c2, c.lo, #32
- // orr t_lo, t_lo, b.hi, lsr t_c2
- // lsr t_hi, b.hi, c.lo
- // a.lo = t_lo
- // a.hi = t_hi
case InstArithmetic::Ashr: {
- // a=b>>c (signed) ==> ...
- // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, and the
- // next orr should be conditioned on PLUS. The last two right shifts
- // should also be arithmetic.
- bool IsAshr = Inst->getOp() == InstArithmetic::Ashr;
- Variable *T_Lo = makeReg(IceType_i32);
+ // a=b>>c
+ // pnacl-llc does:
+ // mov t_b.lo, b.lo
+ // mov t_b.hi, b.hi
+ // mov t_c.lo, c.lo
+ // lsr T0, t_b.lo, t_c.lo
+ // rsb T1, t_c.lo, #32
+ // orr t_a.lo, T0, t_b.hi, lsl T1
+ // sub T2, t_c.lo, #32
+ // cmp T2, #0
+ // [al]srge t_a.lo, t_b.hi, T2
+ // [al]sr t_a.hi, t_b.hi, t_c.lo
+ // mov a.lo, t_a.lo
+ // mov a.hi, t_a.hi
+ //
+ // GCC 4.8 does (lsr):
+ // rsb t_c1, c.lo, #32
+ // lsr t_lo, b.lo, c.lo
+ // orr t_lo, t_lo, b.hi, lsl t_c1
+ // sub t_c2, c.lo, #32
+ // orr t_lo, t_lo, b.hi, lsr t_c2
+ // lsr t_hi, b.hi, c.lo
+ // mov a.lo, t_lo
+ // mov a.hi, t_hi
+ //
+ // These are incompatible, therefore we mimic pnacl-llc.
+ const bool IsAshr = Inst->getOp() == InstArithmetic::Ashr;
+ Constant *_32 = Ctx->getConstantInt32(32);
+ Constant *_0 = Ctx->getConstantZero(IceType_i32);
Variable *Src1RLo = legalizeToReg(Src1Lo);
- Constant *ThirtyTwo = Ctx->getConstantInt32(32);
- Variable *T_C1 = makeReg(IceType_i32);
- Variable *T_C2 = makeReg(IceType_i32);
- _rsb(T_C1, Src1RLo, ThirtyTwo);
- _lsr(T_Lo, Src0RLo, Src1RLo);
- _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
- OperandARM32::LSL, T_C1));
- OperandARM32::ShiftKind RShiftKind;
- CondARM32::Cond Pred;
+ Variable *T0 = makeReg(IceType_i32);
+ Variable *T1 = makeReg(IceType_i32);
+ Variable *T2 = makeReg(IceType_i32);
+ Variable *TA_Lo = makeReg(IceType_i32);
+ Variable *TA_Hi = makeReg(IceType_i32);
+ _lsr(T0, Src0RLo, Src1RLo);
+ _rsb(T1, Src1RLo, _32);
+ _orr(TA_Lo, T0, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
+ OperandARM32::LSL, T1));
+ _sub(T2, Src1RLo, _32);
+ _cmp(T2, _0);
if (IsAshr) {
- _subs(T_C2, Src1RLo, ThirtyTwo);
- RShiftKind = OperandARM32::ASR;
- Pred = CondARM32::PL;
+ _asr(TA_Lo, Src0RHi, T2, CondARM32::GE);
+ _set_dest_nonkillable();
+ _asr(TA_Hi, Src0RHi, Src1RLo);
} else {
- _sub(T_C2, Src1RLo, ThirtyTwo);
- RShiftKind = OperandARM32::LSR;
- Pred = CondARM32::AL;
+ _lsr(TA_Lo, Src0RHi, T2, CondARM32::GE);
+ _set_dest_nonkillable();
+ _lsr(TA_Hi, Src0RHi, Src1RLo);
}
- _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
- RShiftKind, T_C2),
- Pred);
- _mov(DestLo, T_Lo);
- Variable *T_Hi = makeReg(IceType_i32);
- _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
- RShiftKind, Src1RLo));
- _mov(DestHi, T_Hi);
+ _mov(DestLo, TA_Lo);
+ _mov(DestHi, TA_Hi);
return;
}
case InstArithmetic::Fadd:
@@ -1527,9 +1583,11 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
}
return;
} else if (isVectorType(Dest->getType())) {
- UnimplementedError(Func->getContext()->getFlags());
// Add a fake def to keep liveness consistent in the meantime.
- Context.insert(InstFakeDef::create(Func, Dest));
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Dest, T);
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
// Dest->getType() is a non-i64 scalar.
@@ -1585,25 +1643,25 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
case InstArithmetic::Fadd: {
Variable *Src1R = legalizeToReg(Src1);
_vadd(T, Src0R, Src1R);
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
case InstArithmetic::Fsub: {
Variable *Src1R = legalizeToReg(Src1);
_vsub(T, Src0R, Src1R);
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
case InstArithmetic::Fmul: {
Variable *Src1R = legalizeToReg(Src1);
_vmul(T, Src0R, Src1R);
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
case InstArithmetic::Fdiv: {
Variable *Src1R = legalizeToReg(Src1);
_vdiv(T, Src0R, Src1R);
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
}
@@ -1677,7 +1735,8 @@ void TargetARM32::lowerAssign(const InstAssign *Inst) {
Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex);
Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
- Variable *T_Lo = nullptr, *T_Hi = nullptr;
+ Variable *T_Lo = makeReg(IceType_i32);
+ Variable *T_Hi = makeReg(IceType_i32);
_mov(T_Lo, Src0Lo);
_mov(DestLo, T_Lo);
_mov(T_Hi, Src0Hi);
@@ -1696,10 +1755,11 @@ void TargetARM32::lowerAssign(const InstAssign *Inst) {
NewSrc = legalize(Src0, Legal_Reg);
}
if (isVectorType(Dest->getType())) {
- UnimplementedError(Func->getContext()->getFlags());
+ Variable *SrcR = legalizeToReg(NewSrc);
+ _mov(Dest, SrcR);
} else if (isFloatingType(Dest->getType())) {
Variable *SrcR = legalizeToReg(NewSrc);
- _vmov(Dest, SrcR);
+ _mov(Dest, SrcR);
} else {
_mov(Dest, NewSrc);
}
@@ -1769,7 +1829,7 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
ParameterAreaSizeBytes =
applyStackAlignmentTy(ParameterAreaSizeBytes, Ty);
StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes));
- ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
+ ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty);
}
}
@@ -1809,19 +1869,6 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
lowerStore(InstStore::create(Func, StackArg.first, Addr));
}
- // Copy arguments to be passed in registers to the appropriate registers.
- for (auto &GPRArg : GPRArgs) {
- Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second);
- // Generate a FakeUse of register arguments so that they do not get dead
- // code eliminated as a result of the FakeKill of scratch registers after
- // the call.
- Context.insert(InstFakeUse::create(Func, Reg));
- }
- for (auto &FPArg : FPArgs) {
- Variable *Reg = legalizeToReg(FPArg.first, FPArg.second);
- Context.insert(InstFakeUse::create(Func, Reg));
- }
-
// Generate the call instruction. Assign its result to a temporary with high
// register allocation weight.
Variable *Dest = Instr->getDest();
@@ -1872,6 +1919,19 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
CallTarget = legalize(CallTarget, Legal_Reg);
}
+
+ // Copy arguments to be passed in registers to the appropriate registers.
+ for (auto &FPArg : FPArgs) {
+ Variable *Reg = legalizeToReg(FPArg.first, FPArg.second);
+ Context.insert(InstFakeUse::create(Func, Reg));
+ }
+ for (auto &GPRArg : GPRArgs) {
+ Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second);
+ // Generate a FakeUse of register arguments so that they do not get dead
+ // code eliminated as a result of the FakeKill of scratch registers after
+ // the call.
+ Context.insert(InstFakeUse::create(Func, Reg));
+ }
Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget);
Context.insert(NewCall);
if (ReturnRegHi)
@@ -1908,7 +1968,7 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
_mov(DestHi, ReturnRegHi);
} else {
if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
- _vmov(Dest, ReturnReg);
+ _mov(Dest, ReturnReg);
} else {
assert(isIntegerType(Dest->getType()) &&
typeWidthInBytes(Dest->getType()) <= 4);
@@ -1918,6 +1978,13 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
}
}
+namespace {
+void forceHiLoInReg(Variable64On32 *Var) {
+ Var->getHi()->setMustHaveReg();
+ Var->getLo()->setMustHaveReg();
+}
+} // end of anonymous namespace
+
void TargetARM32::lowerCast(const InstCast *Inst) {
InstCast::OpKind CastKind = Inst->getCastKind();
Variable *Dest = Inst->getDest();
@@ -1928,6 +1995,9 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
return;
case InstCast::Sext: {
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
} else if (Dest->getType() == IceType_i64) {
// t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2
@@ -1978,6 +2048,9 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Zext: {
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
} else if (Dest->getType() == IceType_i64) {
// t1=uxtb src; dst.lo=t1; dst.hi=0
@@ -2024,6 +2097,9 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Trunc: {
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
} else {
if (Src0->getType() == IceType_i64)
@@ -2044,6 +2120,9 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// fpext: dest.f64 = fptrunc src0.fp32
const bool IsTrunc = CastKind == InstCast::Fptrunc;
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
break;
}
@@ -2057,6 +2136,26 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Fptosi:
case InstCast::Fptoui: {
+ if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ }
+
+ const bool DestIsSigned = CastKind == InstCast::Fptosi;
+ const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
+ if (llvm::isa<Variable64On32>(Dest)) {
+ const char *HelperName =
+ Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
+ : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64);
+ static constexpr SizeT MaxSrcs = 1;
+ InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
+ Call->addArg(Src0);
+ lowerCall(Call);
+ break;
+ }
// fptosi:
// t1.fp = vcvt src0.fp
// t2.i32 = vmov t1.fp
@@ -2065,28 +2164,14 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// t1.fp = vcvt src0.fp
// t2.u32 = vmov t1.fp
// dest.uint = conv t2.u32 @ Truncates the result if needed.
- if (isVectorType(Dest->getType())) {
- UnimplementedError(Func->getContext()->getFlags());
- break;
- }
- if (auto *Dest64On32 = llvm::dyn_cast<Variable64On32>(Dest)) {
- Context.insert(InstFakeDef::create(Func, Dest64On32->getLo()));
- Context.insert(InstFakeDef::create(Func, Dest64On32->getHi()));
- UnimplementedError(Func->getContext()->getFlags());
- break;
- }
- const bool DestIsSigned = CastKind == InstCast::Fptosi;
Variable *Src0R = legalizeToReg(Src0);
Variable *T_fp = makeReg(IceType_f32);
- if (isFloat32Asserting32Or64(Src0->getType())) {
- _vcvt(T_fp, Src0R,
- DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui);
- } else {
- _vcvt(T_fp, Src0R,
- DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui);
- }
+ const InstARM32Vcvt::VcvtVariant Conversion =
+ Src0IsF32 ? (DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui)
+ : (DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui);
+ _vcvt(T_fp, Src0R, Conversion);
Variable *T = makeReg(IceType_i32);
- _vmov(T, T_fp);
+ _mov(T, T_fp);
if (Dest->getType() != IceType_i32) {
Variable *T_1 = makeReg(Dest->getType());
lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T));
@@ -2097,6 +2182,25 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Sitofp:
case InstCast::Uitofp: {
+ if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ }
+ const bool SourceIsSigned = CastKind == InstCast::Sitofp;
+ const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
+ if (Src0->getType() == IceType_i64) {
+ const char *HelperName =
+ DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32)
+ : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64);
+ static constexpr SizeT MaxSrcs = 1;
+ InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
+ Call->addArg(Src0);
+ lowerCall(Call);
+ break;
+ }
// sitofp:
// t1.i32 = sext src.int @ sign-extends src0 if needed.
// t2.fp32 = vmov t1.i32
@@ -2105,17 +2209,6 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// t1.i32 = zext src.int @ zero-extends src0 if needed.
// t2.fp32 = vmov t1.i32
// t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
- if (isVectorType(Dest->getType())) {
- UnimplementedError(Func->getContext()->getFlags());
- break;
- }
- if (Src0->getType() == IceType_i64) {
- // avoid cryptic liveness errors
- Context.insert(InstFakeDef::create(Func, Dest));
- UnimplementedError(Func->getContext()->getFlags());
- break;
- }
- const bool SourceIsSigned = CastKind == InstCast::Sitofp;
if (Src0->getType() != IceType_i32) {
Variable *Src0R_32 = makeReg(IceType_i32);
lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext
@@ -2125,16 +2218,14 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
Variable *Src0R = legalizeToReg(Src0);
Variable *Src0R_f32 = makeReg(IceType_f32);
- _vmov(Src0R_f32, Src0R);
+ _mov(Src0R_f32, Src0R);
Src0R = Src0R_f32;
Variable *T = makeReg(Dest->getType());
- if (isFloat32Asserting32Or64(Dest->getType())) {
- _vcvt(T, Src0R,
- SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s);
- } else {
- _vcvt(T, Src0R,
- SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d);
- }
+ const InstARM32Vcvt::VcvtVariant Conversion =
+ DestIsF32
+ ? (SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s)
+ : (SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d);
+ _vcvt(T, Src0R, Conversion);
_mov(Dest, T);
break;
}
@@ -2153,9 +2244,6 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case IceType_i1:
UnimplementedError(Func->getContext()->getFlags());
break;
- case IceType_v4i1:
- UnimplementedError(Func->getContext()->getFlags());
- break;
case IceType_i8:
UnimplementedError(Func->getContext()->getFlags());
break;
@@ -2166,7 +2254,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case IceType_f32: {
Variable *Src0R = legalizeToReg(Src0);
Variable *T = makeReg(DestType);
- _vmov(T, Src0R);
+ _mov(T, Src0R);
lowerAssign(InstAssign::create(Func, Dest, T));
break;
}
@@ -2175,13 +2263,17 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// dest[31..0] = t0
// dest[63..32] = t1
assert(Src0->getType() == IceType_f64);
- Variable *T0 = makeReg(IceType_i32);
- Variable *T1 = makeReg(IceType_i32);
+ auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
+ T->initHiLo(Func);
+ forceHiLoInReg(T);
Variable *Src0R = legalizeToReg(Src0);
- _vmov(InstARM32Vmov::RegisterPair(T0, T1), Src0R);
+ _mov(T, Src0R);
+ Context.insert(InstFakeDef::create(Func, T->getLo()));
+ Context.insert(InstFakeDef::create(Func, T->getHi()));
auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
- lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T0));
- lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T1));
+ lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo()));
+ lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi()));
+ Context.insert(InstFakeUse::create(Func, T));
break;
}
case IceType_f64: {
@@ -2190,41 +2282,47 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// vmov T2, T0, T1
// Dest <- T2
assert(Src0->getType() == IceType_i64);
- Variable *SrcLo = legalizeToReg(loOperand(Src0));
- Variable *SrcHi = legalizeToReg(hiOperand(Src0));
- Variable *T = makeReg(IceType_f64);
- _vmov(T, InstARM32Vmov::RegisterPair(SrcLo, SrcHi));
+ auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
+ Src64->initHiLo(Func);
+ forceHiLoInReg(Src64);
+ Variable *T = Src64->getLo();
+ _mov(T, legalizeToReg(loOperand(Src0)));
+ T = Src64->getHi();
+ _mov(T, legalizeToReg(hiOperand(Src0)));
+ T = makeReg(IceType_f64);
+ Context.insert(InstFakeDef::create(Func, Src64));
+ _mov(T, Src64);
+ Context.insert(InstFakeUse::create(Func, Src64->getLo()));
+ Context.insert(InstFakeUse::create(Func, Src64->getHi()));
lowerAssign(InstAssign::create(Func, Dest, T));
break;
}
+ case IceType_v4i1:
case IceType_v8i1:
- UnimplementedError(Func->getContext()->getFlags());
- break;
case IceType_v16i1:
- UnimplementedError(Func->getContext()->getFlags());
- break;
case IceType_v8i16:
- UnimplementedError(Func->getContext()->getFlags());
- break;
case IceType_v16i8:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case IceType_v4i32:
- // avoid cryptic liveness errors
- Context.insert(InstFakeDef::create(Func, Dest));
- UnimplementedError(Func->getContext()->getFlags());
- break;
case IceType_v4f32:
+ case IceType_v4i32: {
+ // avoid cryptic liveness errors
+ Variable *T = makeReg(DestType);
+ Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
break;
}
+ }
break;
}
}
}
void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) {
- (void)Inst;
+ Variable *Dest = Inst->getDest();
+ Type DestType = Dest->getType();
+ Variable *T = makeReg(DestType);
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
}
@@ -2269,6 +2367,9 @@ struct {
void TargetARM32::lowerFcmp(const InstFcmp *Inst) {
Variable *Dest = Inst->getDest();
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
return;
}
@@ -2306,6 +2407,9 @@ void TargetARM32::lowerIcmp(const InstIcmp *Inst) {
Operand *Src1 = legalizeUndef(Inst->getSrc(1));
if (isVectorType(Dest->getType())) {
+ Variable *T = makeReg(Dest->getType());
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
return;
}
@@ -2514,7 +2618,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
if (Val->getType() == IceType_i64) {
Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
Constant *Zero = Ctx->getConstantZero(IceType_i32);
- Variable *T = nullptr;
+ Variable *T = makeReg(Zero->getType());
_mov(T, Zero);
_mov(DestHi, T);
}
@@ -2561,9 +2665,18 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
return;
}
case Intrinsics::Fabs: {
- // Add a fake def to keep liveness consistent in the meantime.
- Context.insert(InstFakeDef::create(Func, Instr->getDest()));
- UnimplementedError(Func->getContext()->getFlags());
+ Variable *Dest = Instr->getDest();
+ Type DestTy = Dest->getType();
+ Variable *T = makeReg(DestTy);
+ if (isVectorType(DestTy)) {
+ // Add a fake def to keep liveness consistent in the meantime.
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Instr->getDest(), T);
+ UnimplementedError(Func->getContext()->getFlags());
+ return;
+ }
+ _vabs(T, legalizeToReg(Instr->getArg(0)));
+ _mov(Dest, T);
return;
}
case Intrinsics::Longjmp: {
@@ -2628,7 +2741,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
Variable *Dest = Instr->getDest();
Variable *T = makeReg(Dest->getType());
_vsqrt(T, Src);
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
case Intrinsics::Stacksave: {
@@ -2674,7 +2787,7 @@ void TargetARM32::lowerCLZ(Variable *Dest, Variable *ValLoR, Variable *ValHiR) {
// of T2 as if it was used as a source.
_set_dest_nonkillable();
_mov(DestLo, T2);
- Variable *T3 = nullptr;
+ Variable *T3 = makeReg(Zero->getType());
_mov(T3, Zero);
_mov(DestHi, T3);
return;
@@ -2734,7 +2847,8 @@ void TargetARM32::lowerRet(const InstRet *Inst) {
Reg = Q0;
} else {
Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex);
- _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0);
+ Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0);
+ _mov(Reg, Src0F, CondARM32::AL);
}
}
// Add a ret instruction even if sandboxing is enabled, because addEpilog
@@ -2758,6 +2872,9 @@ void TargetARM32::lowerSelect(const InstSelect *Inst) {
Operand *Condition = Inst->getCondition();
if (isVectorType(DestTy)) {
+ Variable *T = makeReg(DestTy);
+ Context.insert(InstFakeDef::create(Func, T));
+ _mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
return;
}
@@ -2772,16 +2889,16 @@ void TargetARM32::lowerSelect(const InstSelect *Inst) {
SrcF = legalizeUndef(SrcF);
// Set the low portion.
Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
- Variable *TLo = nullptr;
Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex);
+ Variable *TLo = makeReg(SrcFLo->getType());
_mov(TLo, SrcFLo);
Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex);
_mov_nonkillable(TLo, SrcTLo, Cond);
_mov(DestLo, TLo);
// Set the high portion.
Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
- Variable *THi = nullptr;
Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex);
+ Variable *THi = makeReg(SrcFHi->getType());
_mov(THi, SrcFHi);
Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex);
_mov_nonkillable(THi, SrcTHi, Cond);
@@ -2793,17 +2910,17 @@ void TargetARM32::lowerSelect(const InstSelect *Inst) {
Variable *T = makeReg(DestTy);
SrcF = legalizeToReg(SrcF);
assert(DestTy == SrcF->getType());
- _vmov(T, SrcF);
+ _mov(T, SrcF);
SrcT = legalizeToReg(SrcT);
assert(DestTy == SrcT->getType());
- _vmov(T, SrcT, Cond);
+ _mov(T, SrcT, Cond);
_set_dest_nonkillable();
- _vmov(Dest, T);
+ _mov(Dest, T);
return;
}
- Variable *T = nullptr;
SrcF = legalize(SrcF, Legal_Reg | Legal_Flex);
+ Variable *T = makeReg(SrcF->getType());
_mov(T, SrcF);
SrcT = legalize(SrcT, Legal_Reg | Legal_Flex);
_mov_nonkillable(T, SrcT, Cond);
@@ -2823,9 +2940,6 @@ void TargetARM32::lowerStore(const InstStore *Inst) {
_str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
_str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
} else {
- if (isVectorType(Ty)) {
- UnimplementedError(Func->getContext()->getFlags());
- }
Variable *ValueR = legalizeToReg(Value);
_str(ValueR, NewAddr);
}
@@ -2878,6 +2992,7 @@ void TargetARM32::prelowerPhis() {
Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
Variable *Reg = makeReg(Ty, RegNum);
+ Context.insert(InstFakeDef::create(Func, Reg));
UnimplementedError(Func->getContext()->getFlags());
return Reg;
}
@@ -2887,16 +3002,7 @@ Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
- if (isVectorType(Ty)) {
- // TODO(jpp): Src must be a register, or an address with base register.
- _vmov(Reg, Src);
- } else if (isFloatingType(Ty)) {
- _vmov(Reg, Src);
- } else {
- // Mov's Src operand can really only be the flexible second operand type or
- // a register. Users should guarantee that.
- _mov(Reg, Src);
- }
+ _mov(Reg, Src);
return Reg;
}
@@ -2912,10 +3018,22 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
// type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we
// can always copy to a register.
if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) {
+ static const struct {
+ bool CanHaveOffset;
+ bool CanHaveIndex;
+ } MemTraits[] = {
+#define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \
+ { (ubits) > 0, rraddr } \
+ ,
+ ICETYPEARM32_TABLE
+#undef X
+ };
// Before doing anything with a Mem operand, we need to ensure that the
// Base and Index components are in physical registers.
Variable *Base = Mem->getBase();
Variable *Index = Mem->getIndex();
+ ConstantInteger32 *Offset = Mem->getOffset();
+ assert(Index == nullptr || Offset == nullptr);
Variable *RegBase = nullptr;
Variable *RegIndex = nullptr;
if (Base) {
@@ -2923,32 +3041,43 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
}
if (Index) {
RegIndex = legalizeToReg(Index);
+ if (!MemTraits[Ty].CanHaveIndex) {
+ Variable *T = makeReg(IceType_i32, getReservedTmpReg());
+ _add(T, RegBase, RegIndex);
+ RegBase = T;
+ RegIndex = nullptr;
+ }
+ }
+ if (Offset && Offset->getValue() != 0) {
+ static constexpr bool SignExt = false;
+ if (!MemTraits[Ty].CanHaveOffset ||
+ !OperandARM32Mem::canHoldOffset(Ty, SignExt, Offset->getValue())) {
+ Variable *T = legalizeToReg(Offset, getReservedTmpReg());
+ _add(T, T, RegBase);
+ RegBase = T;
+ Offset = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0));
+ }
}
+
// Create a new operand if there was a change.
if (Base != RegBase || Index != RegIndex) {
// There is only a reg +/- reg or reg + imm form.
// Figure out which to re-create.
- if (Mem->isRegReg()) {
+ if (RegBase && RegIndex) {
Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex,
Mem->getShiftOp(), Mem->getShiftAmt(),
Mem->getAddrMode());
} else {
- Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(),
+ Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset,
Mem->getAddrMode());
}
}
- if (!(Allowed & Legal_Mem)) {
+ if (Allowed & Legal_Mem) {
+ From = Mem;
+ } else {
Variable *Reg = makeReg(Ty, RegNum);
- if (isVectorType(Ty)) {
- UnimplementedError(Func->getContext()->getFlags());
- } else if (isFloatingType(Ty)) {
- _vldr(Reg, Mem);
- } else {
- _ldr(Reg, Mem);
- }
+ _ldr(Reg, Mem);
From = Reg;
- } else {
- From = Mem;
}
return From;
}
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698