summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM64
diff options
context:
space:
mode:
authorWeiming Zhao <weimingz@codeaurora.org>2014-04-30 21:07:24 +0000
committerWeiming Zhao <weimingz@codeaurora.org>2014-04-30 21:07:24 +0000
commit7f6daf1799a0dc93e37edc4d83ba4ef7c184e3a6 (patch)
treedb7cc9066440bf1a9e4106da6c979e0ecdae8272 /llvm/lib/Target/ARM64
parentdd2647edcf99a9e7b1af9b407ff1489b4ee45739 (diff)
downloadbcm5719-llvm-7f6daf1799a0dc93e37edc4d83ba4ef7c184e3a6.tar.gz
bcm5719-llvm-7f6daf1799a0dc93e37edc4d83ba4ef7c184e3a6.zip
[ARM64] Prevent bit extraction to be adjusted by following shift
For pattern like ((x >> C1) & Mask) << C2, DAG combiner may convert it into (x >> (C1-C2)) & (Mask << C2), which makes pattern matching of ubfx more difficult. For example: Given %shr = lshr i64 %x, 4 %and = and i64 %shr, 15 %arrayidx = getelementptr inbounds [8 x [64 x i64]]* @arr, i64 0, %i64 2, i64 %and %0 = load i64* %arrayidx With current shift folding, it takes 3 instrs to compute base address: lsr x8, x0, #1 and x8, x8, #0x78 add x8, x9, x8 If using ubfx, it only needs 2 instrs: ubfx x8, x0, #4, #4 add x8, x9, x8, lsl #3 This fixes bug 19589 llvm-svn: 207702
Diffstat (limited to 'llvm/lib/Target/ARM64')
-rw-r--r--llvm/lib/Target/ARM64/ARM64ISelLowering.cpp15
-rw-r--r--llvm/lib/Target/ARM64/ARM64ISelLowering.h3
2 files changed, 18 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp b/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp
index ccd80175faf..6dd588c3705 100644
--- a/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp
+++ b/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp
@@ -5931,6 +5931,21 @@ ARM64TargetLowering::getScratchRegisters(CallingConv::ID) const {
return ScratchRegs;
}
+bool ARM64TargetLowering::isDesirableToCommuteWithShift(const SDNode *N) const {
+ EVT VT = N->getValueType(0);
+ // If N is unsigned bit extraction: ((x >> C) & mask), then do not combine
+ // it with shift to let it be lowered to UBFX.
+ if (N->getOpcode() == ISD::AND && (VT == MVT::i32 || VT == MVT::i64) &&
+ isa<ConstantSDNode>(N->getOperand(1))) {
+ uint64_t TruncMask = N->getConstantOperandVal(1);
+ if (isMask_64(TruncMask) &&
+ N->getOperand(0).getOpcode() == ISD::SRL &&
+ isa<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
+ return false;
+ }
+ return true;
+}
+
bool ARM64TargetLowering::shouldConvertConstantLoadToIntImm(const APInt &Imm,
Type *Ty) const {
assert(Ty->isIntegerTy());
diff --git a/llvm/lib/Target/ARM64/ARM64ISelLowering.h b/llvm/lib/Target/ARM64/ARM64ISelLowering.h
index ddaf347bf1a..96a32ea85c0 100644
--- a/llvm/lib/Target/ARM64/ARM64ISelLowering.h
+++ b/llvm/lib/Target/ARM64/ARM64ISelLowering.h
@@ -284,6 +284,9 @@ public:
const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override;
+ /// \brief Returns false if N is a bit extraction pattern of (X >> C) & Mask.
+ bool isDesirableToCommuteWithShift(const SDNode *N) const override;
+
/// \brief Returns true if it is beneficial to convert a load of a constant
/// to just the constant itself.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
OpenPOWER on IntegriCloud