From: Peter Collingbourne Date: Wed, 9 Nov 2016 23:53:43 +0000 (+0000) Subject: Re-apply r286384, "X86: Introduce the "relocImm" ComplexPattern, which represents... X-Git-Tag: llvmorg-4.0.0-rc1~5073 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=32ab3a817d4d8ae20e868e8966ceef1511a88d03;p=platform%2Fupstream%2Fllvm.git 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. llvm-svn: 286420 --- diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index d4815c9..4ddf7d7 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -1165,10 +1165,12 @@ class Pat : Pattern; // e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; // class ComplexPattern roots = [], list props = []> { + list roots = [], list props = [], + int complexity = -1> { ValueType Ty = ty; int NumOperands = numops; string SelectFunc = fn; list RootNodes = roots; list Properties = props; + int Complexity = complexity; } diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index e9d0f67..516d067 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -228,6 +228,7 @@ namespace { SDValue &Index, SDValue &Disp, SDValue &Segment, SDValue &NodeWithChain); + bool selectRelocImm(SDValue N, SDValue &Op); bool tryFoldLoad(SDNode *P, SDValue N, SDValue &Base, SDValue &Scale, @@ -1704,6 +1705,27 @@ bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue N, SDValue &Base, return true; } +bool X86DAGToDAGISel::selectRelocImm(SDValue N, SDValue &Op) { + if (auto *CN = dyn_cast(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, SDValue &Base, SDValue &Scale, diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index 4264b5b..e5cd1ef 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -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)>; } -// 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 // into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of // the MOV64ri32 should accept these. diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index fd08209..cb18619 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -5303,6 +5303,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, case X86::CMP16ri: case X86::CMP16ri8: case X86::CMP8ri: + if (!MI.getOperand(1).isImm()) + return false; SrcReg = MI.getOperand(0).getReg(); SrcReg2 = 0; CmpMask = ~0; @@ -5334,6 +5336,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, case X86::SUB16ri: case X86::SUB16ri8: case X86::SUB8ri: + if (!MI.getOperand(2).isImm()) + return false; SrcReg = MI.getOperand(1).getReg(); SrcReg2 = 0; CmpMask = ~0; diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 0476138..0118503 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -765,6 +765,12 @@ def tls64baseaddr : ComplexPattern; +// 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; + //===----------------------------------------------------------------------===// // X86 Instruction Predicate Definitions. def TruePredicate : Predicate<"true">; @@ -877,8 +883,6 @@ def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; 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 ||" "TM.getCodeModel() == CodeModel::Kernel">; def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; @@ -950,7 +954,7 @@ def imm8_su : PatLeaf<(i8 imm), [{ def imm16_su : PatLeaf<(i16 imm), [{ return !shouldAvoidImmediateInstFormsForSize(N); }]>; -def imm32_su : PatLeaf<(i32 imm), [{ +def imm32_su : PatLeaf<(i32 relocImm), [{ return !shouldAvoidImmediateInstFormsForSize(N); }]>; 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; def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$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), "mov{q}\t{$src, $dst|$dst, $src}", [(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 { def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$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 diff --git a/llvm/test/CodeGen/X86/compare-global.ll b/llvm/test/CodeGen/X86/compare-global.ll new file mode 100644 index 0000000..8e3d3a9 --- /dev/null +++ b/llvm/test/CodeGen/X86/compare-global.ll @@ -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() diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index c8ced6b..3cc7b1b 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -805,14 +805,9 @@ static unsigned getPatternSize(const TreePatternNode *P, if (P->isLeaf() && isa(P->getLeafValue())) 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); if (AM) { - Size += AM->getNumOperands() * 3; + Size += AM->getComplexity(); // We don't want to count any children twice, so return early. return Size; diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index e87ffb7..42fbb98 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -393,6 +393,16 @@ ComplexPattern::ComplexPattern(Record *R) { SelectFunc = R->getValueAsString("SelectFunc"); 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. Properties = 0; std::vector PropList = R->getValueAsListOfDefs("Properties"); diff --git a/llvm/utils/TableGen/CodeGenTarget.h b/llvm/utils/TableGen/CodeGenTarget.h index b16750c..9a9522e 100644 --- a/llvm/utils/TableGen/CodeGenTarget.h +++ b/llvm/utils/TableGen/CodeGenTarget.h @@ -196,8 +196,8 @@ class ComplexPattern { std::string SelectFunc; std::vector RootNodes; unsigned Properties; // Node properties + unsigned Complexity; public: - ComplexPattern() : NumOperands(0) {} ComplexPattern(Record *R); MVT::SimpleValueType getValueType() const { return Ty; } @@ -207,6 +207,7 @@ public: return RootNodes; } bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } + unsigned getComplexity() const { return Complexity; } }; } // End llvm namespace