diff options
author | Juergen Ributzka <juergen@apple.com> | 2014-08-29 00:19:21 +0000 |
---|---|---|
committer | Juergen Ributzka <juergen@apple.com> | 2014-08-29 00:19:21 +0000 |
commit | 77bc09f5ab4433cbb0ab9a6c2a75ece1ff241537 (patch) | |
tree | af7337c87c47f384c9c3f6339d6da5a05f9f6645 /llvm/lib | |
parent | 0a20f5417c9d241f4774a49da6c7ca8123686671 (diff) | |
download | llvm-77bc09f5ab4433cbb0ab9a6c2a75ece1ff241537.zip llvm-77bc09f5ab4433cbb0ab9a6c2a75ece1ff241537.tar.gz llvm-77bc09f5ab4433cbb0ab9a6c2a75ece1ff241537.tar.bz2 |
[FastISel][AArch64] Don't fold instructions that are not in the same basic block.
This fix checks first if the instruction to be folded (e.g. sign-/zero-extend,
or shift) is in the same machine basic block as the instruction we are folding
into.
Not doing so can result in incorrect code, because the value might not be
live-out of the basic block, where the value is defined.
This fixes rdar://problem/18169495.
llvm-svn: 216700
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64FastISel.cpp | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index df294bd..179fe4d 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -134,6 +134,7 @@ private: // Utility helper routines. bool isTypeLegal(Type *Ty, MVT &VT); bool isLoadStoreTypeLegal(Type *Ty, MVT &VT); + bool isValueAvailable(const Value *V) const; bool ComputeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr); bool ComputeCallAddress(const Value *V, Address &Addr); bool SimplifyAddress(Address &Addr, MVT VT); @@ -679,6 +680,17 @@ bool AArch64FastISel::isLoadStoreTypeLegal(Type *Ty, MVT &VT) { return false; } +bool AArch64FastISel::isValueAvailable(const Value *V) const { + if (!isa<Instruction>(V)) + return true; + + const auto *I = cast<Instruction>(V); + if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) + return true; + + return false; +} + bool AArch64FastISel::SimplifyAddress(Address &Addr, MVT VT) { unsigned ScaleFactor; switch (VT.SimpleTy) { @@ -853,7 +865,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT, std::swap(LHS, RHS); // Canonicalize shift immediate to the RHS. - if (UseAdds) + if (UseAdds && isValueAvailable(LHS)) if (const auto *SI = dyn_cast<BinaryOperator>(LHS)) if (isa<ConstantInt>(SI->getOperand(1))) if (SI->getOpcode() == Instruction::Shl || @@ -883,7 +895,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT, return ResultReg; // Only extend the RHS within the instruction if there is a valid extend type. - if (ExtendType != AArch64_AM::InvalidShiftExtend) { + if (ExtendType != AArch64_AM::InvalidShiftExtend && isValueAvailable(RHS)) { if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) if ((SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) { @@ -904,26 +916,27 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT, } // Check if the shift can be folded into the instruction. - if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) { - if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) { - AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend; - switch (SI->getOpcode()) { - default: break; - case Instruction::Shl: ShiftType = AArch64_AM::LSL; break; - case Instruction::LShr: ShiftType = AArch64_AM::LSR; break; - case Instruction::AShr: ShiftType = AArch64_AM::ASR; break; - } - uint64_t ShiftVal = C->getZExtValue(); - if (ShiftType != AArch64_AM::InvalidShiftExtend) { - unsigned RHSReg = getRegForValue(SI->getOperand(0)); - if (!RHSReg) - return 0; - bool RHSIsKill = hasTrivialKill(SI->getOperand(0)); - return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, - RHSIsKill, ShiftType, ShiftVal, WantResult); + if (isValueAvailable(RHS)) + if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) { + if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) { + AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend; + switch (SI->getOpcode()) { + default: break; + case Instruction::Shl: ShiftType = AArch64_AM::LSL; break; + case Instruction::LShr: ShiftType = AArch64_AM::LSR; break; + case Instruction::AShr: ShiftType = AArch64_AM::ASR; break; + } + uint64_t ShiftVal = C->getZExtValue(); + if (ShiftType != AArch64_AM::InvalidShiftExtend) { + unsigned RHSReg = getRegForValue(SI->getOperand(0)); + if (!RHSReg) + return 0; + bool RHSIsKill = hasTrivialKill(SI->getOperand(0)); + return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, + RHSIsKill, ShiftType, ShiftVal, WantResult); + } } } - } unsigned RHSReg = getRegForValue(RHS); if (!RHSReg) @@ -3281,17 +3294,19 @@ bool AArch64FastISel::SelectShift(const Instruction *I) { uint64_t ShiftVal = C->getZExtValue(); MVT SrcVT = RetVT; bool IsZExt = (I->getOpcode() == Instruction::AShr) ? false : true; - const Value * Op0 = I->getOperand(0); + const Value *Op0 = I->getOperand(0); if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) { MVT TmpVT; - if (isLoadStoreTypeLegal(ZExt->getSrcTy(), TmpVT)) { + if (isValueAvailable(ZExt) && + isLoadStoreTypeLegal(ZExt->getSrcTy(), TmpVT)) { SrcVT = TmpVT; IsZExt = true; Op0 = ZExt->getOperand(0); } } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) { MVT TmpVT; - if (isLoadStoreTypeLegal(SExt->getSrcTy(), TmpVT)) { + if (isValueAvailable(SExt) && + isLoadStoreTypeLegal(SExt->getSrcTy(), TmpVT)) { SrcVT = TmpVT; IsZExt = false; Op0 = SExt->getOperand(0); |