Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit fa1cf8c

Browse files
author
Weiming Zhao
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207702 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 79844fc commit fa1cf8c

File tree

5 files changed

+43
-0
lines changed

5 files changed

+43
-0
lines changed

include/llvm/Target/TargetLowering.h

+9
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,15 @@ class TargetLowering : public TargetLoweringBase {
20172017
///
20182018
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
20192019

2020+
/// Return true if it is profitable to move a following shift through this
2021+
// node, adjusting any immediate operands as necessary to preserve semantics.
2022+
// This transformation may not be desirable if it disrupts a particularly
2023+
// auspicious target-specific tree (e.g. bitfield extractionon in AArch64).
2024+
// By default, it returns true.
2025+
virtual bool isDesirableToCommuteWithShift(const SDNode *N /*Op*/) const {
2026+
return true;
2027+
}
2028+
20202029
/// Return true if the target has native support for the specified value type
20212030
/// and it is 'desirable' to use the type for the given node type. e.g. On x86
20222031
/// i16 is legal, but undesirable since i16 instruction encodings are longer

lib/CodeGen/SelectionDAG/DAGCombiner.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -3867,6 +3867,9 @@ SDValue DAGCombiner::visitShiftByConstant(SDNode *N, ConstantSDNode *Amt) {
38673867
return SDValue();
38683868
}
38693869

3870+
if (!TLI.isDesirableToCommuteWithShift(LHS))
3871+
return SDValue();
3872+
38703873
// Fold the constants, shifting the binop RHS by the shift amount.
38713874
SDValue NewRHS = DAG.getNode(N->getOpcode(), SDLoc(LHS->getOperand(1)),
38723875
N->getValueType(0),

lib/Target/ARM64/ARM64ISelLowering.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -5931,6 +5931,21 @@ ARM64TargetLowering::getScratchRegisters(CallingConv::ID) const {
59315931
return ScratchRegs;
59325932
}
59335933

5934+
bool ARM64TargetLowering::isDesirableToCommuteWithShift(const SDNode *N) const {
5935+
EVT VT = N->getValueType(0);
5936+
// If N is unsigned bit extraction: ((x >> C) & mask), then do not combine
5937+
// it with shift to let it be lowered to UBFX.
5938+
if (N->getOpcode() == ISD::AND && (VT == MVT::i32 || VT == MVT::i64) &&
5939+
isa<ConstantSDNode>(N->getOperand(1))) {
5940+
uint64_t TruncMask = N->getConstantOperandVal(1);
5941+
if (isMask_64(TruncMask) &&
5942+
N->getOperand(0).getOpcode() == ISD::SRL &&
5943+
isa<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
5944+
return false;
5945+
}
5946+
return true;
5947+
}
5948+
59345949
bool ARM64TargetLowering::shouldConvertConstantLoadToIntImm(const APInt &Imm,
59355950
Type *Ty) const {
59365951
assert(Ty->isIntegerTy());

lib/Target/ARM64/ARM64ISelLowering.h

+3
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ class ARM64TargetLowering : public TargetLowering {
284284

285285
const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override;
286286

287+
/// \brief Returns false if N is a bit extraction pattern of (X >> C) & Mask.
288+
bool isDesirableToCommuteWithShift(const SDNode *N) const override;
289+
287290
/// \brief Returns true if it is beneficial to convert a load of a constant
288291
/// to just the constant itself.
289292
bool shouldConvertConstantLoadToIntImm(const APInt &Imm,

test/CodeGen/ARM64/bitfield-extract.ll

+13
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,19 @@ end:
501501
ret i80 %conv3
502502
}
503503

504+
; Check if we can still catch UBFX when "AND" is used by SHL.
505+
; CHECK-LABEL: fct21:
506+
; CHECK: ubfx
507+
@arr = external global [8 x [64 x i64]]
508+
define i64 @fct21(i64 %x) {
509+
entry:
510+
%shr = lshr i64 %x, 4
511+
%and = and i64 %shr, 15
512+
%arrayidx = getelementptr inbounds [8 x [64 x i64]]* @arr, i64 0, i64 0, i64 %and
513+
%0 = load i64* %arrayidx, align 8
514+
ret i64 %0
515+
}
516+
504517
define i16 @test_ignored_rightbits(i32 %dst, i32 %in) {
505518
; CHECK-LABEL: test_ignored_rightbits:
506519

0 commit comments

Comments
 (0)