Index: src/IceTargetLoweringARM32.cpp |
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
index 10fdfe12a1b4a6f7c1b9a6bb334caa0e5d8530bb..0dbcfb1df2a98085e13ff2d62704893d701ae960 100644 |
--- a/src/IceTargetLoweringARM32.cpp |
+++ b/src/IceTargetLoweringARM32.cpp |
@@ -863,14 +863,14 @@ Operand *TargetARM32::loOperand(Operand *Operand) { |
assert(Operand->getType() == IceType_i64); |
if (Operand->getType() != IceType_i64) |
return Operand; |
- if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
+ if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { |
split64(Var); |
return Var->getLo(); |
} |
- if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
+ if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
} |
- if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
+ if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
// Conservatively disallow memory operands with side-effects (pre/post |
// increment) in case of duplication. |
assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
@@ -892,15 +892,15 @@ Operand *TargetARM32::hiOperand(Operand *Operand) { |
assert(Operand->getType() == IceType_i64); |
if (Operand->getType() != IceType_i64) |
return Operand; |
- if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
+ if (auto *Var = llvm::dyn_cast<Variable>(Operand)) { |
split64(Var); |
return Var->getHi(); |
} |
- if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
+ if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
return Ctx->getConstantInt32( |
static_cast<uint32_t>(Const->getValue() >> 32)); |
} |
- if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
+ if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { |
// Conservatively disallow memory operands with side-effects |
// in case of duplication. |
assert(Mem->getAddrMode() == OperandARM32Mem::Offset || |
@@ -1012,7 +1012,7 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) { |
} else { |
// Non-constant sizes need to be adjusted to the next highest |
// multiple of the required alignment at runtime. |
- TotalSize = legalize(TotalSize); |
+ TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
Variable *T = makeReg(IceType_i32); |
_mov(T, TotalSize); |
Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
@@ -1101,8 +1101,8 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
// Or it may be the case that the operands aren't swapped, but the |
// bits can be flipped and a different operation applied. |
// E.g., use BIC (bit clear) instead of AND for some masks. |
- Operand *Src0 = Inst->getSrc(0); |
- Operand *Src1 = Inst->getSrc(1); |
+ Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
+ Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
if (Dest->getType() == IceType_i64) { |
// These helper-call-involved instructions are lowered in this |
// separate switch. This is because we would otherwise assume that |
@@ -1458,9 +1458,9 @@ void TargetARM32::lowerAssign(const InstAssign *Inst) { |
Operand *Src0 = Inst->getSrc(0); |
assert(Dest->getType() == Src0->getType()); |
if (Dest->getType() == IceType_i64) { |
- Src0 = legalize(Src0); |
- Operand *Src0Lo = loOperand(Src0); |
- Operand *Src0Hi = hiOperand(Src0); |
+ Src0 = legalizeUndef(Src0); |
+ Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
+ 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; |
@@ -1523,7 +1523,7 @@ void TargetARM32::lowerCall(const InstCall *Instr) { |
// Classify each argument operand according to the location where the |
// argument is passed. |
for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
- Operand *Arg = Instr->getArg(i); |
+ Operand *Arg = legalizeUndef(Instr->getArg(i)); |
Type Ty = Arg->getType(); |
bool InRegs = false; |
if (isVectorType(Ty)) { |
@@ -1703,7 +1703,7 @@ void TargetARM32::lowerCall(const InstCall *Instr) { |
void TargetARM32::lowerCast(const InstCast *Inst) { |
InstCast::OpKind CastKind = Inst->getCastKind(); |
Variable *Dest = Inst->getDest(); |
- Operand *Src0 = Inst->getSrc(0); |
+ Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
switch (CastKind) { |
default: |
Func->setError("Cast type not supported"); |
@@ -1808,7 +1808,6 @@ void TargetARM32::lowerCast(const InstCast *Inst) { |
if (isVectorType(Dest->getType())) { |
UnimplementedError(Func->getContext()->getFlags()); |
} else { |
- Operand *Src0 = Inst->getSrc(0); |
if (Src0->getType() == IceType_i64) |
Src0 = loOperand(Src0); |
Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
@@ -1866,8 +1865,8 @@ void TargetARM32::lowerFcmp(const InstFcmp *Inst) { |
void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
Variable *Dest = Inst->getDest(); |
- Operand *Src0 = Inst->getSrc(0); |
- Operand *Src1 = Inst->getSrc(1); |
+ Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
+ Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
if (isVectorType(Dest->getType())) { |
UnimplementedError(Func->getContext()->getFlags()); |
@@ -2036,6 +2035,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
Operand *Val = Instr->getArg(0); |
Type Ty = Val->getType(); |
if (Ty == IceType_i64) { |
+ Val = legalizeUndef(Val); |
Variable *Val_Lo = legalizeToVar(loOperand(Val)); |
Variable *Val_Hi = legalizeToVar(hiOperand(Val)); |
Variable *T_Lo = makeReg(IceType_i32); |
@@ -2088,6 +2088,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
Variable *ValLoR; |
Variable *ValHiR = nullptr; |
if (Val->getType() == IceType_i64) { |
+ Val = legalizeUndef(Val); |
ValLoR = legalizeToVar(loOperand(Val)); |
ValHiR = legalizeToVar(hiOperand(Val)); |
} else { |
@@ -2102,6 +2103,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
Variable *ValLoR; |
Variable *ValHiR = nullptr; |
if (Val->getType() == IceType_i64) { |
+ Val = legalizeUndef(Val); |
ValLoR = legalizeToVar(loOperand(Val)); |
ValHiR = legalizeToVar(hiOperand(Val)); |
Variable *TLo = makeReg(IceType_i32); |
@@ -2268,6 +2270,7 @@ void TargetARM32::lowerRet(const InstRet *Inst) { |
if (Inst->hasRetValue()) { |
Operand *Src0 = Inst->getRetValue(); |
if (Src0->getType() == IceType_i64) { |
+ Src0 = legalizeUndef(Src0); |
Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); |
Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); |
Reg = R0; |
@@ -2318,6 +2321,8 @@ void TargetARM32::lowerSelect(const InstSelect *Inst) { |
_cmp(CmpOpnd0, CmpOpnd1); |
CondARM32::Cond Cond = CondARM32::NE; |
if (DestTy == IceType_i64) { |
+ SrcT = legalizeUndef(SrcT); |
+ SrcF = legalizeUndef(SrcF); |
// Set the low portion. |
Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
Variable *TLo = nullptr; |
@@ -2351,6 +2356,7 @@ void TargetARM32::lowerStore(const InstStore *Inst) { |
Type Ty = NewAddr->getType(); |
if (Ty == IceType_i64) { |
+ Value = legalizeUndef(Value); |
Variable *ValueHi = legalizeToVar(hiOperand(Value)); |
Variable *ValueLo = legalizeToVar(loOperand(Value)); |
_str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
@@ -2373,7 +2379,7 @@ void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
Operand *Src0 = Inst->getComparison(); |
SizeT NumCases = Inst->getNumCases(); |
if (Src0->getType() == IceType_i64) { |
- // TODO(jvoung): handle and test undef for Src0 |
+ Src0 = legalizeUndef(Src0); |
Variable *Src0Lo = legalizeToVar(loOperand(Src0)); |
Variable *Src0Hi = legalizeToVar(hiOperand(Src0)); |
for (SizeT I = 0; I < NumCases; ++I) { |
@@ -2444,6 +2450,7 @@ Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
int32_t RegNum) { |
+ Type Ty = From->getType(); |
// Assert that a physical register is allowed. To date, all calls |
// to legalize() allow a physical register. Legal_Flex converts |
// registers to the right type OperandARM32FlexReg as needed. |
@@ -2471,16 +2478,15 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
// There is only a reg +/- reg or reg + imm form. |
// Figure out which to re-create. |
if (Mem->isRegReg()) { |
- Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, RegIndex, |
+ Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
Mem->getShiftOp(), Mem->getShiftAmt(), |
Mem->getAddrMode()); |
} else { |
- Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, |
- Mem->getOffset(), Mem->getAddrMode()); |
+ Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), |
+ Mem->getAddrMode()); |
} |
} |
if (!(Allowed & Legal_Mem)) { |
- Type Ty = Mem->getType(); |
Variable *Reg = makeReg(Ty, RegNum); |
_ldr(Reg, Mem); |
From = Reg; |
@@ -2510,17 +2516,14 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
if (llvm::isa<Constant>(From)) { |
if (llvm::isa<ConstantUndef>(From)) { |
- // Lower undefs to zero. Another option is to lower undefs to an |
- // uninitialized register; however, using an uninitialized register |
- // results in less predictable code. |
- if (isVectorType(From->getType())) |
- return makeVectorOfZeros(From->getType(), RegNum); |
- From = Ctx->getConstantZero(From->getType()); |
+ From = legalizeUndef(From, RegNum); |
+ if (isVectorType(Ty)) |
+ return From; |
} |
// There should be no constants of vector type (other than undef). |
- assert(!isVectorType(From->getType())); |
+ assert(!isVectorType(Ty)); |
bool CanBeFlex = Allowed & Legal_Flex; |
- if (auto C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
+ if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
uint32_t RotateAmt; |
uint32_t Immed_8; |
uint32_t Value = static_cast<uint32_t>(C32->getValue()); |
@@ -2530,19 +2533,16 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
// Also try the inverse and use MVN if possible. |
if (CanBeFlex && |
OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { |
- return OperandARM32FlexImm::create(Func, From->getType(), Immed_8, |
- RotateAmt); |
+ return OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt); |
} else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( |
~Value, &RotateAmt, &Immed_8)) { |
- auto InvertedFlex = OperandARM32FlexImm::create(Func, From->getType(), |
- Immed_8, RotateAmt); |
- Type Ty = From->getType(); |
+ auto InvertedFlex = |
+ OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt); |
Variable *Reg = makeReg(Ty, RegNum); |
_mvn(Reg, InvertedFlex); |
return Reg; |
} else { |
// Do a movw/movt to a register. |
- Type Ty = From->getType(); |
Variable *Reg = makeReg(Ty, RegNum); |
uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
_movw(Reg, |
@@ -2552,8 +2552,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
} |
return Reg; |
} |
- } else if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
- Type Ty = From->getType(); |
+ } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
Variable *Reg = makeReg(Ty, RegNum); |
_movw(Reg, C); |
_movt(Reg, C); |
@@ -2586,11 +2585,33 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
return From; |
} |
-// Provide a trivial wrapper to legalize() for this common usage. |
+/// Provide a trivial wrapper to legalize() for this common usage. |
Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { |
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
} |
+/// Legalize undef values to concrete values. |
+Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { |
+ Type Ty = From->getType(); |
+ if (llvm::isa<ConstantUndef>(From)) { |
+ // Lower undefs to zero. Another option is to lower undefs to an |
+ // uninitialized register; however, using an uninitialized register |
+ // results in less predictable code. |
+ // |
+ // If in the future the implementation is changed to lower undef |
+ // values to uninitialized registers, a FakeDef will be needed: |
+ // Context.insert(InstFakeDef::create(Func, Reg)); |
+ // This is in order to ensure that the live range of Reg is not |
+ // overestimated. If the constant being lowered is a 64 bit value, |
+ // then the result should be split and the lo and hi components will |
+ // need to go in uninitialized registers. |
+ if (isVectorType(Ty)) |
+ return makeVectorOfZeros(Ty, RegNum); |
+ return Ctx->getConstantZero(Ty); |
+ } |
+ return From; |
+} |
+ |
OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { |
OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); |
// It may be the case that address mode optimization already creates |