mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-01 15:19:05 +00:00
Re-apply r286384, "X86: Introduce the "relocImm" ComplexPattern, which represents a relocatable immediate.", with a fix for 32-bit x86.
Teach X86InstrInfo::analyzeCompare() not to crash on CMP and SUB instructions that take a global address operand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286420 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
619ca04281
commit
027f4d03c6
@ -1165,10 +1165,12 @@ class Pat<dag pattern, dag result> : Pattern<pattern, [result]>;
|
|||||||
// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>;
|
// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>;
|
||||||
//
|
//
|
||||||
class ComplexPattern<ValueType ty, int numops, string fn,
|
class ComplexPattern<ValueType ty, int numops, string fn,
|
||||||
list<SDNode> roots = [], list<SDNodeProperty> props = []> {
|
list<SDNode> roots = [], list<SDNodeProperty> props = [],
|
||||||
|
int complexity = -1> {
|
||||||
ValueType Ty = ty;
|
ValueType Ty = ty;
|
||||||
int NumOperands = numops;
|
int NumOperands = numops;
|
||||||
string SelectFunc = fn;
|
string SelectFunc = fn;
|
||||||
list<SDNode> RootNodes = roots;
|
list<SDNode> RootNodes = roots;
|
||||||
list<SDNodeProperty> Properties = props;
|
list<SDNodeProperty> Properties = props;
|
||||||
|
int Complexity = complexity;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +228,7 @@ namespace {
|
|||||||
SDValue &Index, SDValue &Disp,
|
SDValue &Index, SDValue &Disp,
|
||||||
SDValue &Segment,
|
SDValue &Segment,
|
||||||
SDValue &NodeWithChain);
|
SDValue &NodeWithChain);
|
||||||
|
bool selectRelocImm(SDValue N, SDValue &Op);
|
||||||
|
|
||||||
bool tryFoldLoad(SDNode *P, SDValue N,
|
bool tryFoldLoad(SDNode *P, SDValue N,
|
||||||
SDValue &Base, SDValue &Scale,
|
SDValue &Base, SDValue &Scale,
|
||||||
@ -1704,6 +1705,27 @@ bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue N, SDValue &Base,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86DAGToDAGISel::selectRelocImm(SDValue N, SDValue &Op) {
|
||||||
|
if (auto *CN = dyn_cast<ConstantSDNode>(N)) {
|
||||||
|
Op = CurDAG->getTargetConstant(CN->getAPIntValue(), SDLoc(CN),
|
||||||
|
N.getValueType());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (N.getOpcode() != X86ISD::Wrapper)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned Opc = N.getOperand(0)->getOpcode();
|
||||||
|
if (Opc == ISD::TargetConstantPool || Opc == ISD::TargetJumpTable ||
|
||||||
|
Opc == ISD::TargetExternalSymbol || Opc == ISD::TargetGlobalAddress ||
|
||||||
|
Opc == ISD::TargetGlobalTLSAddress || Opc == ISD::MCSymbol ||
|
||||||
|
Opc == ISD::TargetBlockAddress) {
|
||||||
|
Op = N.getOperand(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool X86DAGToDAGISel::tryFoldLoad(SDNode *P, SDValue N,
|
bool X86DAGToDAGISel::tryFoldLoad(SDNode *P, SDValue N,
|
||||||
SDValue &Base, SDValue &Scale,
|
SDValue &Base, SDValue &Scale,
|
||||||
|
@ -1025,53 +1025,6 @@ def : Pat<(store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>;
|
|||||||
def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>;
|
def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable
|
|
||||||
def : Pat<(i32 (X86Wrapper tconstpool :$dst)), (MOV32ri tconstpool :$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper tjumptable :$dst)), (MOV32ri tjumptable :$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper tglobaltlsaddr:$dst)),(MOV32ri tglobaltlsaddr:$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper mcsym:$dst)), (MOV32ri mcsym:$dst)>;
|
|
||||||
def : Pat<(i32 (X86Wrapper tblockaddress:$dst)), (MOV32ri tblockaddress:$dst)>;
|
|
||||||
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper tconstpool:$src2)),
|
|
||||||
(ADD32ri GR32:$src1, tconstpool:$src2)>;
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper tjumptable:$src2)),
|
|
||||||
(ADD32ri GR32:$src1, tjumptable:$src2)>;
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper tglobaladdr :$src2)),
|
|
||||||
(ADD32ri GR32:$src1, tglobaladdr:$src2)>;
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper texternalsym:$src2)),
|
|
||||||
(ADD32ri GR32:$src1, texternalsym:$src2)>;
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper mcsym:$src2)),
|
|
||||||
(ADD32ri GR32:$src1, mcsym:$src2)>;
|
|
||||||
def : Pat<(add GR32:$src1, (X86Wrapper tblockaddress:$src2)),
|
|
||||||
(ADD32ri GR32:$src1, tblockaddress:$src2)>;
|
|
||||||
|
|
||||||
def : Pat<(store (i32 (X86Wrapper tglobaladdr:$src)), addr:$dst),
|
|
||||||
(MOV32mi addr:$dst, tglobaladdr:$src)>;
|
|
||||||
def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst),
|
|
||||||
(MOV32mi addr:$dst, texternalsym:$src)>;
|
|
||||||
def : Pat<(store (i32 (X86Wrapper mcsym:$src)), addr:$dst),
|
|
||||||
(MOV32mi addr:$dst, mcsym:$src)>;
|
|
||||||
def : Pat<(store (i32 (X86Wrapper tblockaddress:$src)), addr:$dst),
|
|
||||||
(MOV32mi addr:$dst, tblockaddress:$src)>;
|
|
||||||
|
|
||||||
// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable when not in small
|
|
||||||
// code model mode, should use 'movabs'. FIXME: This is really a hack, the
|
|
||||||
// 'movabs' predicate should handle this sort of thing.
|
|
||||||
def : Pat<(i64 (X86Wrapper tconstpool :$dst)),
|
|
||||||
(MOV64ri tconstpool :$dst)>, Requires<[FarData]>;
|
|
||||||
def : Pat<(i64 (X86Wrapper tjumptable :$dst)),
|
|
||||||
(MOV64ri tjumptable :$dst)>, Requires<[FarData]>;
|
|
||||||
def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
|
|
||||||
(MOV64ri tglobaladdr :$dst)>, Requires<[FarData]>;
|
|
||||||
def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
|
|
||||||
(MOV64ri texternalsym:$dst)>, Requires<[FarData]>;
|
|
||||||
def : Pat<(i64 (X86Wrapper mcsym:$dst)),
|
|
||||||
(MOV64ri mcsym:$dst)>, Requires<[FarData]>;
|
|
||||||
def : Pat<(i64 (X86Wrapper tblockaddress:$dst)),
|
|
||||||
(MOV64ri tblockaddress:$dst)>, Requires<[FarData]>;
|
|
||||||
|
|
||||||
// In kernel code model, we can get the address of a label
|
// In kernel code model, we can get the address of a label
|
||||||
// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of
|
// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of
|
||||||
// the MOV64ri32 should accept these.
|
// the MOV64ri32 should accept these.
|
||||||
|
@ -5303,6 +5303,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
|
|||||||
case X86::CMP16ri:
|
case X86::CMP16ri:
|
||||||
case X86::CMP16ri8:
|
case X86::CMP16ri8:
|
||||||
case X86::CMP8ri:
|
case X86::CMP8ri:
|
||||||
|
if (!MI.getOperand(1).isImm())
|
||||||
|
return false;
|
||||||
SrcReg = MI.getOperand(0).getReg();
|
SrcReg = MI.getOperand(0).getReg();
|
||||||
SrcReg2 = 0;
|
SrcReg2 = 0;
|
||||||
CmpMask = ~0;
|
CmpMask = ~0;
|
||||||
@ -5334,6 +5336,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
|
|||||||
case X86::SUB16ri:
|
case X86::SUB16ri:
|
||||||
case X86::SUB16ri8:
|
case X86::SUB16ri8:
|
||||||
case X86::SUB8ri:
|
case X86::SUB8ri:
|
||||||
|
if (!MI.getOperand(2).isImm())
|
||||||
|
return false;
|
||||||
SrcReg = MI.getOperand(1).getReg();
|
SrcReg = MI.getOperand(1).getReg();
|
||||||
SrcReg2 = 0;
|
SrcReg2 = 0;
|
||||||
CmpMask = ~0;
|
CmpMask = ~0;
|
||||||
|
@ -765,6 +765,12 @@ def tls64baseaddr : ComplexPattern<i64, 5, "selectTLSADDRAddr",
|
|||||||
|
|
||||||
def vectoraddr : ComplexPattern<iPTR, 5, "selectVectorAddr", [],[SDNPWantParent]>;
|
def vectoraddr : ComplexPattern<iPTR, 5, "selectVectorAddr", [],[SDNPWantParent]>;
|
||||||
|
|
||||||
|
// A relocatable immediate is either an immediate operand or an operand that can
|
||||||
|
// be relocated by the linker to an immediate, such as a regular symbol in
|
||||||
|
// non-PIC code.
|
||||||
|
def relocImm : ComplexPattern<iAny, 1, "selectRelocImm", [imm, X86Wrapper], [],
|
||||||
|
0>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// X86 Instruction Predicate Definitions.
|
// X86 Instruction Predicate Definitions.
|
||||||
def TruePredicate : Predicate<"true">;
|
def TruePredicate : Predicate<"true">;
|
||||||
@ -877,8 +883,6 @@ def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">;
|
|||||||
def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">;
|
def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">;
|
||||||
def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
|
def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
|
||||||
def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">;
|
def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">;
|
||||||
def FarData : Predicate<"TM.getCodeModel() != CodeModel::Small &&"
|
|
||||||
"TM.getCodeModel() != CodeModel::Kernel">;
|
|
||||||
def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
|
def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
|
||||||
"TM.getCodeModel() == CodeModel::Kernel">;
|
"TM.getCodeModel() == CodeModel::Kernel">;
|
||||||
def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
|
def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
|
||||||
@ -950,7 +954,7 @@ def imm8_su : PatLeaf<(i8 imm), [{
|
|||||||
def imm16_su : PatLeaf<(i16 imm), [{
|
def imm16_su : PatLeaf<(i16 imm), [{
|
||||||
return !shouldAvoidImmediateInstFormsForSize(N);
|
return !shouldAvoidImmediateInstFormsForSize(N);
|
||||||
}]>;
|
}]>;
|
||||||
def imm32_su : PatLeaf<(i32 imm), [{
|
def imm32_su : PatLeaf<(i32 relocImm), [{
|
||||||
return !shouldAvoidImmediateInstFormsForSize(N);
|
return !shouldAvoidImmediateInstFormsForSize(N);
|
||||||
}]>;
|
}]>;
|
||||||
def i64immSExt32_su : PatLeaf<(i64immSExt32), [{
|
def i64immSExt32_su : PatLeaf<(i64immSExt32), [{
|
||||||
@ -1380,7 +1384,7 @@ def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src),
|
|||||||
[(set GR16:$dst, imm:$src)], IIC_MOV>, OpSize16;
|
[(set GR16:$dst, imm:$src)], IIC_MOV>, OpSize16;
|
||||||
def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src),
|
def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src),
|
||||||
"mov{l}\t{$src, $dst|$dst, $src}",
|
"mov{l}\t{$src, $dst|$dst, $src}",
|
||||||
[(set GR32:$dst, imm:$src)], IIC_MOV>, OpSize32;
|
[(set GR32:$dst, relocImm:$src)], IIC_MOV>, OpSize32;
|
||||||
def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src),
|
def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src),
|
||||||
"mov{q}\t{$src, $dst|$dst, $src}",
|
"mov{q}\t{$src, $dst|$dst, $src}",
|
||||||
[(set GR64:$dst, i64immSExt32:$src)], IIC_MOV>;
|
[(set GR64:$dst, i64immSExt32:$src)], IIC_MOV>;
|
||||||
@ -1388,7 +1392,7 @@ def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src),
|
|||||||
let isReMaterializable = 1 in {
|
let isReMaterializable = 1 in {
|
||||||
def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src),
|
def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src),
|
||||||
"movabs{q}\t{$src, $dst|$dst, $src}",
|
"movabs{q}\t{$src, $dst|$dst, $src}",
|
||||||
[(set GR64:$dst, imm:$src)], IIC_MOV>;
|
[(set GR64:$dst, relocImm:$src)], IIC_MOV>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Longer forms that use a ModR/M byte. Needed for disassembler
|
// Longer forms that use a ModR/M byte. Needed for disassembler
|
||||||
|
22
test/CodeGen/X86/compare-global.ll
Normal file
22
test/CodeGen/X86/compare-global.ll
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
; RUN: llc -o - %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
||||||
|
target triple = "i686-pc-windows-msvc18.0.0"
|
||||||
|
|
||||||
|
@foo = external global i8
|
||||||
|
|
||||||
|
define void @f(i8* %c) {
|
||||||
|
entry:
|
||||||
|
; CHECK: subl $_foo, %eax
|
||||||
|
%cmp = icmp eq i8* %c, @foo
|
||||||
|
br i1 %cmp, label %if.then, label %if.end
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
tail call void @g()
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @g()
|
@ -805,14 +805,9 @@ static unsigned getPatternSize(const TreePatternNode *P,
|
|||||||
if (P->isLeaf() && isa<IntInit>(P->getLeafValue()))
|
if (P->isLeaf() && isa<IntInit>(P->getLeafValue()))
|
||||||
Size += 2;
|
Size += 2;
|
||||||
|
|
||||||
// FIXME: This is a hack to statically increase the priority of patterns
|
|
||||||
// which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
|
|
||||||
// Later we can allow complexity / cost for each pattern to be (optionally)
|
|
||||||
// specified. To get best possible pattern match we'll need to dynamically
|
|
||||||
// calculate the complexity of all patterns a dag can potentially map to.
|
|
||||||
const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
|
const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
|
||||||
if (AM) {
|
if (AM) {
|
||||||
Size += AM->getNumOperands() * 3;
|
Size += AM->getComplexity();
|
||||||
|
|
||||||
// We don't want to count any children twice, so return early.
|
// We don't want to count any children twice, so return early.
|
||||||
return Size;
|
return Size;
|
||||||
|
@ -393,6 +393,16 @@ ComplexPattern::ComplexPattern(Record *R) {
|
|||||||
SelectFunc = R->getValueAsString("SelectFunc");
|
SelectFunc = R->getValueAsString("SelectFunc");
|
||||||
RootNodes = R->getValueAsListOfDefs("RootNodes");
|
RootNodes = R->getValueAsListOfDefs("RootNodes");
|
||||||
|
|
||||||
|
// FIXME: This is a hack to statically increase the priority of patterns which
|
||||||
|
// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
|
||||||
|
// possible pattern match we'll need to dynamically calculate the complexity
|
||||||
|
// of all patterns a dag can potentially map to.
|
||||||
|
int64_t RawComplexity = R->getValueAsInt("Complexity");
|
||||||
|
if (RawComplexity == -1)
|
||||||
|
Complexity = NumOperands * 3;
|
||||||
|
else
|
||||||
|
Complexity = RawComplexity;
|
||||||
|
|
||||||
// Parse the properties.
|
// Parse the properties.
|
||||||
Properties = 0;
|
Properties = 0;
|
||||||
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
|
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
|
||||||
|
@ -196,8 +196,8 @@ class ComplexPattern {
|
|||||||
std::string SelectFunc;
|
std::string SelectFunc;
|
||||||
std::vector<Record*> RootNodes;
|
std::vector<Record*> RootNodes;
|
||||||
unsigned Properties; // Node properties
|
unsigned Properties; // Node properties
|
||||||
|
unsigned Complexity;
|
||||||
public:
|
public:
|
||||||
ComplexPattern() : NumOperands(0) {}
|
|
||||||
ComplexPattern(Record *R);
|
ComplexPattern(Record *R);
|
||||||
|
|
||||||
MVT::SimpleValueType getValueType() const { return Ty; }
|
MVT::SimpleValueType getValueType() const { return Ty; }
|
||||||
@ -207,6 +207,7 @@ public:
|
|||||||
return RootNodes;
|
return RootNodes;
|
||||||
}
|
}
|
||||||
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
|
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
|
||||||
|
unsigned getComplexity() const { return Complexity; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
Loading…
x
Reference in New Issue
Block a user