Index: llvm/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAG.h +++ llvm/include/llvm/CodeGen/SelectionDAG.h @@ -531,6 +531,8 @@ unsigned char TargetFlags = 0) { return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags); } + SDValue getAbsoluteAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, + bool isTarget = false); SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false); SDValue getTargetFrameIndex(int FI, EVT VT) { return getFrameIndex(FI, VT, true); Index: llvm/include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1330,7 +1330,7 @@ }; class ConstantSDNode : public SDNode { - const ConstantInt *Value; + PointerUnion Value; friend class SelectionDAG; ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, const DebugLoc &DL, EVT VT) @@ -1339,19 +1339,33 @@ Value(val) { ConstantSDNodeBits.IsOpaque = isOpaque; } + ConstantSDNode(bool isTarget, const GlobalValue *GV, const DebugLoc &DL, + EVT VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL, + getSDVTList(VT)), + Value(GV) { + ConstantSDNodeBits.IsOpaque = true; + } + public: + bool isInt() const { return Value.is(); } - const ConstantInt *getConstantIntValue() const { return Value; } - const APInt &getAPIntValue() const { return Value->getValue(); } - uint64_t getZExtValue() const { return Value->getZExtValue(); } - int64_t getSExtValue() const { return Value->getSExtValue(); } + const ConstantInt *getConstantIntValue() const { + return Value.get(); + } + const APInt &getAPIntValue() const { return getConstantIntValue()->getValue(); } + uint64_t getZExtValue() const { return getConstantIntValue()->getZExtValue(); } + int64_t getSExtValue() const { return getConstantIntValue()->getSExtValue(); } - bool isOne() const { return Value->isOne(); } - bool isNullValue() const { return Value->isNullValue(); } - bool isAllOnesValue() const { return Value->isAllOnesValue(); } + bool isOne() const { return getConstantIntValue()->isOne(); } + bool isNullValue() const { return getConstantIntValue()->isNullValue(); } + bool isAllOnesValue() const { return getConstantIntValue()->isAllOnesValue(); } bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; } + bool isGlobal() const { return Value.is(); } + const GlobalValue *getGlobal() const { return Value.get(); } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::Constant || N->getOpcode() == ISD::TargetConstant; Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -790,7 +790,8 @@ // int. static ConstantSDNode *isConstOrConstSplat(SDValue N) { if (ConstantSDNode *CN = dyn_cast(N)) - return CN; + if (CN->isInt()) + return CN; if (BuildVectorSDNode *BV = dyn_cast(N)) { BitVector UndefElements; @@ -3156,7 +3157,8 @@ // vector as a scalar and use the splat value. APInt Constant = APInt::getNullValue(1); if (const ConstantSDNode *C = dyn_cast(N1)) { - Constant = C->getAPIntValue(); + if (C->isInt()) + Constant = C->getAPIntValue(); } else if (BuildVectorSDNode *Vector = dyn_cast(N1)) { APInt SplatValue, SplatUndef; unsigned SplatBitSize; Index: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -388,7 +388,10 @@ AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap, IsDebug, IsClone, IsCloned); } else if (ConstantSDNode *C = dyn_cast(Op)) { - MIB.addImm(C->getSExtValue()); + if (C->isGlobal()) + MIB.addGlobalAddress(C->getGlobal(), 0, 0); + else + MIB.addImm(C->getSExtValue()); } else if (ConstantFPSDNode *F = dyn_cast(Op)) { MIB.addFPImm(F->getConstantFPValue()); } else if (RegisterSDNode *R = dyn_cast(Op)) { Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -386,7 +386,10 @@ case ISD::TargetConstant: case ISD::Constant: { const ConstantSDNode *C = cast(N); - ID.AddPointer(C->getConstantIntValue()); + if (C->isInt()) + ID.AddPointer(C->getConstantIntValue()); + else + ID.AddPointer(C->getGlobal()); ID.AddBoolean(C->isOpaque()); break; } @@ -1274,6 +1277,21 @@ return SDValue(N, 0); } +SDValue SelectionDAG::getAbsoluteAddress(const GlobalValue *GV, const SDLoc &DL, + EVT VT, bool isTarget) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::Constant, getVTList(VT), None); + ID.AddPointer(GV); + void *IP = nullptr; + if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) + return SDValue(E, 0); + + auto *N = newSDNode(isTarget, GV, DL.getDebugLoc(), VT); + CSEMap.InsertNode(N, IP); + InsertNode(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) { unsigned Opc = isTarget ? ISD::TargetFrameIndex : ISD::FrameIndex; FoldingSetNodeID ID; @@ -2008,6 +2026,8 @@ switch (Op.getOpcode()) { case ISD::Constant: + if (!cast(Op)->isInt()) + break; // We know all of the bits for a constant! KnownOne = cast(Op)->getAPIntValue(); KnownZero = ~KnownOne; @@ -6665,7 +6685,7 @@ bool llvm::isNullConstant(SDValue V) { ConstantSDNode *Const = dyn_cast(V); - return Const != nullptr && Const->isNullValue(); + return Const != nullptr && Const->isInt() && Const->isNullValue(); } bool llvm::isNullFPConstant(SDValue V) { @@ -6675,12 +6695,12 @@ bool llvm::isAllOnesConstant(SDValue V) { ConstantSDNode *Const = dyn_cast(V); - return Const != nullptr && Const->isAllOnesValue(); + return Const != nullptr && Const->isInt() && Const->isAllOnesValue(); } bool llvm::isOneConstant(SDValue V) { ConstantSDNode *Const = dyn_cast(V); - return Const != nullptr && Const->isOne(); + return Const != nullptr && Const->isInt() && Const->isOne(); } bool llvm::isBitwiseNot(SDValue V) { Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -422,7 +422,12 @@ } OS << ">"; } else if (const ConstantSDNode *CSDN = dyn_cast(this)) { - OS << '<' << CSDN->getAPIntValue() << '>'; + OS << '<'; + if (CSDN->isGlobal()) + CSDN->getGlobal()->printAsOperand(OS); + else + OS << CSDN->getAPIntValue(); + OS << '>'; } else if (const ConstantFPSDNode *CSDN = dyn_cast(this)) { if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) OS << '<' << CSDN->getValueAPF().convertToFloat() << '>'; Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2557,7 +2557,7 @@ Val = GetVBR(Val, MatcherTable, MatcherIndex); ConstantSDNode *C = dyn_cast(N); - return C && C->getSExtValue() == Val; + return C && C->isInt() && C->getSExtValue() == Val; } LLVM_ATTRIBUTE_ALWAYS_INLINE static inline bool @@ -3183,9 +3183,15 @@ SDValue Imm = RecordedNodes[RecNo].first; if (Imm->getOpcode() == ISD::Constant) { - const ConstantInt *Val=cast(Imm)->getConstantIntValue(); - Imm = CurDAG->getTargetConstant(*Val, SDLoc(NodeToMatch), - Imm.getValueType()); + auto ImmC = cast(Imm); + if (ImmC->isInt()) { + const ConstantInt *Val = ImmC->getConstantIntValue(); + Imm = CurDAG->getTargetConstant(*Val, SDLoc(NodeToMatch), + Imm.getValueType()); + } else { + Imm = CurDAG->getAbsoluteAddress( + ImmC->getGlobal(), SDLoc(NodeToMatch), Imm.getValueType(), true); + } } else if (Imm->getOpcode() == ISD::ConstantFP) { const ConstantFP *Val=cast(Imm)->getConstantFPValue(); Imm = CurDAG->getTargetConstantFP(*Val, SDLoc(NodeToMatch), Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -348,7 +348,7 @@ case ISD::AND: case ISD::OR: { ConstantSDNode *C = dyn_cast(Op.getOperand(1)); - if (!C) return false; + if (!C || !C->isInt()) return false; if (Op.getOpcode() == ISD::XOR && (C->getAPIntValue() | (~Demanded)).isAllOnesValue()) @@ -464,6 +464,8 @@ APInt KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut; switch (Op.getOpcode()) { case ISD::Constant: + if (!cast(Op)->isInt()) + break; // We know all of the bits for a constant! KnownOne = cast(Op)->getAPIntValue(); KnownZero = ~KnownOne; @@ -501,16 +503,18 @@ // simplify the LHS, here we're using information from the LHS to simplify // the RHS. if (ConstantSDNode *RHSC = dyn_cast(Op.getOperand(1))) { - APInt LHSZero, LHSOne; - // Do not increment Depth here; that can cause an infinite loop. - TLO.DAG.computeKnownBits(Op.getOperand(0), LHSZero, LHSOne, Depth); - // If the LHS already has zeros where RHSC does, this and is dead. - if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask)) - return TLO.CombineTo(Op, Op.getOperand(0)); - // If any of the set bits in the RHS are known zero on the LHS, shrink - // the constant. - if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask)) - return true; + if (RHSC->isInt()) { + APInt LHSZero, LHSOne; + // Do not increment Depth here; that can cause an infinite loop. + TLO.DAG.computeKnownBits(Op.getOperand(0), LHSZero, LHSOne, Depth); + // If the LHS already has zeros where RHSC does, this and is dead. + if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + // If any of the set bits in the RHS are known zero on the LHS, shrink + // the constant. + if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask)) + return true; + } } if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -30321,6 +30322,35 @@ return truncateVectorCompareWithPACKSS(VT, In, DL, DAG, Subtarget); } +static SDValue combineAbsoluteSymbolReference(EVT VT, SDNode *N, + SelectionDAG &DAG, + const X86Subtarget &Subtarget) { + if (!Subtarget.isTargetELF() || + N->getOperand(0)->getOpcode() != ISD::TargetGlobalAddress) + return SDValue(); + + auto GO = dyn_cast( + cast(N->getOperand(0))->getGlobal()); + if (!GO) + return SDValue(); + + MDNode *MD = GO->getMetadata(LLVMContext::MD_range); + if (!MD) + return SDValue(); + + ConstantRange CR = getConstantRangeFromMetadata(*MD); + if (CR.getUnsignedMax().uge(1 << VT.getSizeInBits())) + return SDValue(); + + SDLoc DL(N); + return DAG.getAbsoluteAddress(GO, DL, VT); +} + +static SDValue combineWrapper(SDNode *N, SelectionDAG &DAG, + const X86Subtarget &Subtarget) { + return combineAbsoluteSymbolReference(N->getValueType(0), N, DAG, Subtarget); +} + static SDValue combineTruncate(SDNode *N, SelectionDAG &DAG, const X86Subtarget &Subtarget) { EVT VT = N->getValueType(0); @@ -30343,6 +30373,11 @@ if (SDValue V = combineVectorCompareTruncation(N, DL, DAG, Subtarget)) return V; + if (Src->getOpcode() == X86ISD::Wrapper) + if (SDValue V = + combineAbsoluteSymbolReference(VT, Src.getNode(), DAG, Subtarget)) + return V; + return combineVectorTruncation(N, DAG, Subtarget); } @@ -31659,6 +31694,7 @@ case ISD::FSUB: return combineFaddFsub(N, DAG, Subtarget); case ISD::FNEG: return combineFneg(N, DAG, Subtarget); case ISD::TRUNCATE: return combineTruncate(N, DAG, Subtarget); + case X86ISD::Wrapper: return combineWrapper(N, DAG, Subtarget); case X86ISD::FXOR: case X86ISD::FOR: return combineFOr(N, DAG, Subtarget); case X86ISD::FMIN: Index: llvm/test/CodeGen/X86/absolute-constant.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/absolute-constant.ll @@ -0,0 +1,27 @@ +; RUN: llc -o - %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@foo = external global i8, align 1, !range !0 + +define void @bar(i8* %x) { +entry: + %0 = load i8, i8* %x, align 1 + %conv = sext i8 %0 to i32 + ; CHECK: testb $foo, (%rdi) + %and = and i32 %conv, sext (i8 ptrtoint (i8* @foo to i8) to i32) + %tobool = icmp eq i32 %and, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + tail call void (...) @xf() + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} + +declare void @xf(...) + +!0 = !{i32 0, i32 256}