diff options
author | Juergen Ributzka <juergen@apple.com> | 2014-09-17 19:51:38 +0000 |
---|---|---|
committer | Juergen Ributzka <juergen@apple.com> | 2014-09-17 19:51:38 +0000 |
commit | 3871c69422d99b2cb674f509799931bf6d8e1e2f (patch) | |
tree | ac8cfd0b953743cf0ea2559ad704bab5593fb1f8 /llvm/lib | |
parent | 22d4cd0a4f57a76e99b63821c99e585fe0dbba76 (diff) | |
download | bcm5719-llvm-3871c69422d99b2cb674f509799931bf6d8e1e2f.tar.gz bcm5719-llvm-3871c69422d99b2cb674f509799931bf6d8e1e2f.zip |
[FastISel][AArch64] Fold mul into add/sub and logical operations.
Try to fold the multiply into the add/sub or logical operations (when
possible).
This is related to rdar://problem/18369687.
llvm-svn: 217978
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64FastISel.cpp | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index f9037a31b04..f4d6665e835 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -949,8 +949,13 @@ unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS, if (UseAdd && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) std::swap(LHS, RHS); + // Canonicalize mul by power of 2 to the RHS. + if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS)) + if (isMulPowOf2(LHS)) + std::swap(LHS, RHS); + // Canonicalize shift immediate to the RHS. - if (UseAdd && isValueAvailable(LHS)) + if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS)) if (const auto *SI = dyn_cast<BinaryOperator>(LHS)) if (isa<ConstantInt>(SI->getOperand(1))) if (SI->getOpcode() == Instruction::Shl || @@ -980,7 +985,8 @@ unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS, return ResultReg; // Only extend the RHS within the instruction if there is a valid extend type. - if (ExtendType != AArch64_AM::InvalidShiftExtend && isValueAvailable(RHS)) { + if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() && + 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)) { @@ -1000,8 +1006,28 @@ unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS, ExtendType, 0, SetFlags, WantResult); } + // Check if the mul can be folded into the instruction. + if (RHS->hasOneUse() && isValueAvailable(RHS)) + if (isMulPowOf2(RHS)) { + const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0); + const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1); + + if (const auto *C = dyn_cast<ConstantInt>(MulLHS)) + if (C->getValue().isPowerOf2()) + std::swap(MulLHS, MulRHS); + + assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt."); + uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2(); + unsigned RHSReg = getRegForValue(MulLHS); + if (!RHSReg) + return 0; + bool RHSIsKill = hasTrivialKill(MulLHS); + return emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill, + AArch64_AM::LSL, ShiftVal, SetFlags, WantResult); + } + // Check if the shift can be folded into the instruction. - if (isValueAvailable(RHS)) + if (RHS->hasOneUse() && 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; @@ -1296,12 +1322,16 @@ unsigned AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) std::swap(LHS, RHS); + // Canonicalize mul by power-of-2 to the RHS. + if (LHS->hasOneUse() && isValueAvailable(LHS)) + if (isMulPowOf2(LHS)) + std::swap(LHS, RHS); + // Canonicalize shift immediate to the RHS. - if (isValueAvailable(LHS)) - if (const auto *SI = dyn_cast<BinaryOperator>(LHS)) + if (LHS->hasOneUse() && isValueAvailable(LHS)) + if (const auto *SI = dyn_cast<ShlOperator>(LHS)) if (isa<ConstantInt>(SI->getOperand(1))) - if (SI->getOpcode() == Instruction::Shl) - std::swap(LHS, RHS); + std::swap(LHS, RHS); unsigned LHSReg = getRegForValue(LHS); if (!LHSReg) @@ -1316,19 +1346,39 @@ unsigned AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, if (ResultReg) return ResultReg; + // Check if the mul can be folded into the instruction. + if (RHS->hasOneUse() && isValueAvailable(RHS)) + if (isMulPowOf2(RHS)) { + const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0); + const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1); + + if (const auto *C = dyn_cast<ConstantInt>(MulLHS)) + if (C->getValue().isPowerOf2()) + std::swap(MulLHS, MulRHS); + + assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt."); + uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2(); + + unsigned RHSReg = getRegForValue(MulLHS); + if (!RHSReg) + return 0; + bool RHSIsKill = hasTrivialKill(MulLHS); + return emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg, + RHSIsKill, ShiftVal); + } + // Check if the shift can be folded into the instruction. - if (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) { - uint64_t ShiftVal = C->getZExtValue(); - unsigned RHSReg = getRegForValue(SI->getOperand(0)); - if (!RHSReg) - return 0; - bool RHSIsKill = hasTrivialKill(SI->getOperand(0)); - return emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg, - RHSIsKill, ShiftVal); - } + if (RHS->hasOneUse() && isValueAvailable(RHS)) + if (const auto *SI = dyn_cast<ShlOperator>(RHS)) + if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) { + uint64_t ShiftVal = C->getZExtValue(); + unsigned RHSReg = getRegForValue(SI->getOperand(0)); + if (!RHSReg) + return 0; + bool RHSIsKill = hasTrivialKill(SI->getOperand(0)); + return emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg, + RHSIsKill, ShiftVal); + } unsigned RHSReg = getRegForValue(RHS); if (!RHSReg) |