forked from OSchip/llvm-project
X86: Introduce relocImm-based patterns for cmp.
Differential Revision: https://reviews.llvm.org/D28690 llvm-svn: 294636
This commit is contained in:
parent
0699ef39ce
commit
ef089bdb4b
|
|
@ -384,6 +384,16 @@ namespace {
|
|||
bool ComplexPatternFuncMutatesDAG() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isSExtAbsoluteSymbolRef(unsigned Width, SDNode *N) const;
|
||||
|
||||
/// Returns whether this is a relocatable immediate in the range
|
||||
/// [-2^Width .. 2^Width-1].
|
||||
template <unsigned Width> bool isSExtRelocImm(SDNode *N) const {
|
||||
if (auto *CN = dyn_cast<ConstantSDNode>(N))
|
||||
return isInt<Width>(CN->getSExtValue());
|
||||
return isSExtAbsoluteSymbolRef(Width, N);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1789,6 +1799,21 @@ SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
|
|||
return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(DL)).getNode();
|
||||
}
|
||||
|
||||
bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(unsigned Width, SDNode *N) const {
|
||||
if (N->getOpcode() == ISD::TRUNCATE)
|
||||
N = N->getOperand(0).getNode();
|
||||
if (N->getOpcode() != X86ISD::Wrapper)
|
||||
return false;
|
||||
|
||||
auto *GA = dyn_cast<GlobalAddressSDNode>(N->getOperand(0));
|
||||
if (!GA)
|
||||
return false;
|
||||
|
||||
Optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
|
||||
return CR && CR->getSignedMin().sge(-1ull << Width) &&
|
||||
CR->getSignedMax().slt(1ull << Width);
|
||||
}
|
||||
|
||||
/// Test whether the given X86ISD::CMP node has any uses which require the SF
|
||||
/// or OF bits to be accurate.
|
||||
static bool hasNoSignedComparisonUses(SDNode *N) {
|
||||
|
|
|
|||
|
|
@ -1743,6 +1743,12 @@ def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>;
|
|||
def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>;
|
||||
def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>;
|
||||
|
||||
// sub reg, relocImm
|
||||
def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt8_su:$src2),
|
||||
(SUB64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>;
|
||||
def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt32_su:$src2),
|
||||
(SUB64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
|
||||
|
||||
// mul reg, reg
|
||||
def : Pat<(mul GR16:$src1, GR16:$src2),
|
||||
(IMUL16rr GR16:$src1, GR16:$src2)>;
|
||||
|
|
|
|||
|
|
@ -933,6 +933,15 @@ def i32immSExt8 : ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
|
|||
def i64immSExt8 : ImmLeaf<i64, [{ return isInt<8>(Imm); }]>;
|
||||
def i64immSExt32 : ImmLeaf<i64, [{ return isInt<32>(Imm); }]>;
|
||||
|
||||
// FIXME: Ideally we would just replace the above i*immSExt* matchers with
|
||||
// relocImm-based matchers, but then FastISel would be unable to use them.
|
||||
def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{
|
||||
return isSExtRelocImm<8>(N);
|
||||
}]>;
|
||||
def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{
|
||||
return isSExtRelocImm<32>(N);
|
||||
}]>;
|
||||
|
||||
// If we have multiple users of an immediate, it's much smaller to reuse
|
||||
// the register, rather than encode the immediate in every instruction.
|
||||
// This has the risk of increasing register pressure from stretched live
|
||||
|
|
@ -973,6 +982,13 @@ def i64immSExt8_su : PatLeaf<(i64immSExt8), [{
|
|||
return !shouldAvoidImmediateInstFormsForSize(N);
|
||||
}]>;
|
||||
|
||||
def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{
|
||||
return !shouldAvoidImmediateInstFormsForSize(N);
|
||||
}]>;
|
||||
def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{
|
||||
return !shouldAvoidImmediateInstFormsForSize(N);
|
||||
}]>;
|
||||
|
||||
// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit
|
||||
// unsigned field.
|
||||
def i64immZExt32 : ImmLeaf<i64, [{ return isUInt<32>(Imm); }]>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
; RUN: llc < %s | FileCheck %s
|
||||
; RUN: llc -relocation-model=pic < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
@cmp8 = external hidden global i8, !absolute_symbol !0
|
||||
@cmp32 = external hidden global i8, !absolute_symbol !1
|
||||
|
||||
declare void @f()
|
||||
|
||||
define void @foo8(i64 %val) {
|
||||
; CHECK: cmpq $cmp8@ABS8, %rdi
|
||||
%cmp = icmp ule i64 %val, ptrtoint (i8* @cmp8 to i64)
|
||||
br i1 %cmp, label %t, label %f
|
||||
|
||||
t:
|
||||
call void @f()
|
||||
ret void
|
||||
|
||||
f:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @foo32(i64 %val) {
|
||||
; CHECK: cmpq $cmp32, %rdi
|
||||
%cmp = icmp ule i64 %val, ptrtoint (i8* @cmp32 to i64)
|
||||
br i1 %cmp, label %t, label %f
|
||||
|
||||
t:
|
||||
call void @f()
|
||||
ret void
|
||||
|
||||
f:
|
||||
ret void
|
||||
}
|
||||
|
||||
!0 = !{i64 0, i64 128}
|
||||
!1 = !{i64 0, i64 2147483648}
|
||||
Loading…
Reference in New Issue