2012-03-13 06:47:27 +01:00
|
|
|
//===-- SelectionDAGDumper.cpp - Implement SelectionDAG::dump() -----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This implements the SelectionDAG::dump method and friends.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2012-03-13 06:47:27 +01:00
|
|
|
#include "ScheduleDAGSDNodes.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2012-03-13 06:47:27 +01:00
|
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2014-03-06 01:46:21 +01:00
|
|
|
#include "llvm/IR/DebugInfo.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/GraphWriter.h"
|
2015-12-04 02:31:59 +01:00
|
|
|
#include "llvm/Support/Printable.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2012-03-13 06:47:27 +01:00
|
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
|
|
#include "llvm/Target/TargetIntrinsicInfo.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
2014-08-04 23:25:23 +02:00
|
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
2012-03-13 06:47:27 +01:00
|
|
|
using namespace llvm;
|
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
static cl::opt<bool>
|
|
|
|
VerboseDAGDumping("dag-dump-verbose", cl::Hidden,
|
|
|
|
cl::desc("Display more information when dumping selection "
|
|
|
|
"DAG nodes."));
|
|
|
|
|
2012-03-13 06:47:27 +01:00
|
|
|
std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
|
|
|
switch (getOpcode()) {
|
|
|
|
default:
|
|
|
|
if (getOpcode() < ISD::BUILTIN_OP_END)
|
|
|
|
return "<<Unknown DAG Node>>";
|
|
|
|
if (isMachineOpcode()) {
|
|
|
|
if (G)
|
2014-08-05 04:39:49 +02:00
|
|
|
if (const TargetInstrInfo *TII = G->getSubtarget().getInstrInfo())
|
2012-03-13 06:47:27 +01:00
|
|
|
if (getMachineOpcode() < TII->getNumOpcodes())
|
|
|
|
return TII->getName(getMachineOpcode());
|
|
|
|
return "<<Unknown Machine Node #" + utostr(getOpcode()) + ">>";
|
|
|
|
}
|
|
|
|
if (G) {
|
|
|
|
const TargetLowering &TLI = G->getTargetLoweringInfo();
|
|
|
|
const char *Name = TLI.getTargetNodeName(getOpcode());
|
|
|
|
if (Name) return Name;
|
|
|
|
return "<<Unknown Target Node #" + utostr(getOpcode()) + ">>";
|
|
|
|
}
|
|
|
|
return "<<Unknown Node #" + utostr(getOpcode()) + ">>";
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
case ISD::DELETED_NODE: return "<<Deleted Node!>>";
|
|
|
|
#endif
|
|
|
|
case ISD::PREFETCH: return "Prefetch";
|
|
|
|
case ISD::ATOMIC_FENCE: return "AtomicFence";
|
|
|
|
case ISD::ATOMIC_CMP_SWAP: return "AtomicCmpSwap";
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 16:24:07 +02:00
|
|
|
case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: return "AtomicCmpSwapWithSuccess";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::ATOMIC_SWAP: return "AtomicSwap";
|
|
|
|
case ISD::ATOMIC_LOAD_ADD: return "AtomicLoadAdd";
|
|
|
|
case ISD::ATOMIC_LOAD_SUB: return "AtomicLoadSub";
|
|
|
|
case ISD::ATOMIC_LOAD_AND: return "AtomicLoadAnd";
|
|
|
|
case ISD::ATOMIC_LOAD_OR: return "AtomicLoadOr";
|
|
|
|
case ISD::ATOMIC_LOAD_XOR: return "AtomicLoadXor";
|
|
|
|
case ISD::ATOMIC_LOAD_NAND: return "AtomicLoadNand";
|
|
|
|
case ISD::ATOMIC_LOAD_MIN: return "AtomicLoadMin";
|
|
|
|
case ISD::ATOMIC_LOAD_MAX: return "AtomicLoadMax";
|
|
|
|
case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin";
|
|
|
|
case ISD::ATOMIC_LOAD_UMAX: return "AtomicLoadUMax";
|
|
|
|
case ISD::ATOMIC_LOAD: return "AtomicLoad";
|
|
|
|
case ISD::ATOMIC_STORE: return "AtomicStore";
|
|
|
|
case ISD::PCMARKER: return "PCMarker";
|
|
|
|
case ISD::READCYCLECOUNTER: return "ReadCycleCounter";
|
|
|
|
case ISD::SRCVALUE: return "SrcValue";
|
|
|
|
case ISD::MDNODE_SDNODE: return "MDNode";
|
|
|
|
case ISD::EntryToken: return "EntryToken";
|
|
|
|
case ISD::TokenFactor: return "TokenFactor";
|
|
|
|
case ISD::AssertSext: return "AssertSext";
|
|
|
|
case ISD::AssertZext: return "AssertZext";
|
|
|
|
|
|
|
|
case ISD::BasicBlock: return "BasicBlock";
|
|
|
|
case ISD::VALUETYPE: return "ValueType";
|
|
|
|
case ISD::Register: return "Register";
|
|
|
|
case ISD::RegisterMask: return "RegisterMask";
|
2014-01-25 03:02:55 +01:00
|
|
|
case ISD::Constant:
|
|
|
|
if (cast<ConstantSDNode>(this)->isOpaque())
|
|
|
|
return "OpaqueConstant";
|
|
|
|
return "Constant";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::ConstantFP: return "ConstantFP";
|
|
|
|
case ISD::GlobalAddress: return "GlobalAddress";
|
|
|
|
case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
|
|
|
|
case ISD::FrameIndex: return "FrameIndex";
|
|
|
|
case ISD::JumpTable: return "JumpTable";
|
|
|
|
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
|
|
|
|
case ISD::RETURNADDR: return "RETURNADDR";
|
|
|
|
case ISD::FRAMEADDR: return "FRAMEADDR";
|
2016-06-19 14:37:52 +02:00
|
|
|
case ISD::LOCAL_RECOVER: return "LOCAL_RECOVER";
|
2014-05-06 18:51:25 +02:00
|
|
|
case ISD::READ_REGISTER: return "READ_REGISTER";
|
|
|
|
case ISD::WRITE_REGISTER: return "WRITE_REGISTER";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET";
|
Add ISD::EH_DWARF_CFA, simplify @llvm.eh.dwarf.cfa on Mips, fix on PowerPC
LLVM has an @llvm.eh.dwarf.cfa intrinsic, used to lower the GCC-compatible
__builtin_dwarf_cfa() builtin. As pointed out in PR26761, this is currently
broken on PowerPC (and likely on ARM as well). Currently, @llvm.eh.dwarf.cfa is
lowered using:
ADD(FRAMEADDR, FRAME_TO_ARGS_OFFSET)
where FRAME_TO_ARGS_OFFSET defaults to the constant zero. On x86,
FRAME_TO_ARGS_OFFSET is lowered to 2*SlotSize. This setup, however, does not
work for PowerPC. Because of the way that the stack layout works, the canonical
frame address is not exactly (FRAMEADDR + FRAME_TO_ARGS_OFFSET) on PowerPC
(there is a lower save-area offset as well), so it is not just a matter of
implementing FRAME_TO_ARGS_OFFSET for PowerPC (unless we redefine its
semantics -- We can do that, since it is currently used only for
@llvm.eh.dwarf.cfa lowering, but the better to directly lower the CFA construct
itself (since it can be easily represented as a fixed-offset FrameIndex)). Mips
currently does this, but by using a custom lowering for ADD that specifically
recognizes the (FRAMEADDR, FRAME_TO_ARGS_OFFSET) pattern.
This change introduces a ISD::EH_DWARF_CFA node, which by default expands using
the existing logic, but can be directly lowered by the target. Mips is updated
to use this method (which simplifies its implementation, and I suspect makes it
more robust), and updates PowerPC to do the same.
Fixes PR26761.
Differential Revision: https://reviews.llvm.org/D24038
llvm-svn: 280350
2016-09-01 12:28:47 +02:00
|
|
|
case ISD::EH_DWARF_CFA: return "EH_DWARF_CFA";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::EH_RETURN: return "EH_RETURN";
|
|
|
|
case ISD::EH_SJLJ_SETJMP: return "EH_SJLJ_SETJMP";
|
|
|
|
case ISD::EH_SJLJ_LONGJMP: return "EH_SJLJ_LONGJMP";
|
2015-07-17 00:34:16 +02:00
|
|
|
case ISD::EH_SJLJ_SETUP_DISPATCH: return "EH_SJLJ_SETUP_DISPATCH";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::ConstantPool: return "ConstantPool";
|
2012-08-08 00:37:05 +02:00
|
|
|
case ISD::TargetIndex: return "TargetIndex";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::ExternalSymbol: return "ExternalSymbol";
|
|
|
|
case ISD::BlockAddress: return "BlockAddress";
|
|
|
|
case ISD::INTRINSIC_WO_CHAIN:
|
|
|
|
case ISD::INTRINSIC_VOID:
|
|
|
|
case ISD::INTRINSIC_W_CHAIN: {
|
|
|
|
unsigned OpNo = getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 0 : 1;
|
|
|
|
unsigned IID = cast<ConstantSDNode>(getOperand(OpNo))->getZExtValue();
|
|
|
|
if (IID < Intrinsic::num_intrinsics)
|
2016-08-23 18:23:45 +02:00
|
|
|
return Intrinsic::getName((Intrinsic::ID)IID, None);
|
2012-03-13 06:47:27 +01:00
|
|
|
else if (const TargetIntrinsicInfo *TII = G->getTarget().getIntrinsicInfo())
|
|
|
|
return TII->getName(IID);
|
|
|
|
llvm_unreachable("Invalid intrinsic ID");
|
|
|
|
}
|
|
|
|
|
|
|
|
case ISD::BUILD_VECTOR: return "BUILD_VECTOR";
|
2014-01-25 03:02:55 +01:00
|
|
|
case ISD::TargetConstant:
|
|
|
|
if (cast<ConstantSDNode>(this)->isOpaque())
|
|
|
|
return "OpaqueTargetConstant";
|
|
|
|
return "TargetConstant";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::TargetConstantFP: return "TargetConstantFP";
|
|
|
|
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
|
|
|
|
case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";
|
|
|
|
case ISD::TargetFrameIndex: return "TargetFrameIndex";
|
|
|
|
case ISD::TargetJumpTable: return "TargetJumpTable";
|
|
|
|
case ISD::TargetConstantPool: return "TargetConstantPool";
|
|
|
|
case ISD::TargetExternalSymbol: return "TargetExternalSymbol";
|
2015-06-22 19:46:53 +02:00
|
|
|
case ISD::MCSymbol: return "MCSymbol";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::TargetBlockAddress: return "TargetBlockAddress";
|
|
|
|
|
|
|
|
case ISD::CopyToReg: return "CopyToReg";
|
|
|
|
case ISD::CopyFromReg: return "CopyFromReg";
|
|
|
|
case ISD::UNDEF: return "undef";
|
|
|
|
case ISD::MERGE_VALUES: return "merge_values";
|
|
|
|
case ISD::INLINEASM: return "inlineasm";
|
|
|
|
case ISD::EH_LABEL: return "eh_label";
|
|
|
|
case ISD::HANDLENODE: return "handlenode";
|
|
|
|
|
|
|
|
// Unary operators
|
|
|
|
case ISD::FABS: return "fabs";
|
2014-10-22 01:01:01 +02:00
|
|
|
case ISD::FMINNUM: return "fminnum";
|
|
|
|
case ISD::FMAXNUM: return "fmaxnum";
|
2015-08-11 11:13:05 +02:00
|
|
|
case ISD::FMINNAN: return "fminnan";
|
|
|
|
case ISD::FMAXNAN: return "fmaxnan";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FNEG: return "fneg";
|
|
|
|
case ISD::FSQRT: return "fsqrt";
|
|
|
|
case ISD::FSIN: return "fsin";
|
|
|
|
case ISD::FCOS: return "fcos";
|
2013-01-29 03:32:37 +01:00
|
|
|
case ISD::FSINCOS: return "fsincos";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FTRUNC: return "ftrunc";
|
|
|
|
case ISD::FFLOOR: return "ffloor";
|
|
|
|
case ISD::FCEIL: return "fceil";
|
|
|
|
case ISD::FRINT: return "frint";
|
|
|
|
case ISD::FNEARBYINT: return "fnearbyint";
|
2013-08-08 00:49:12 +02:00
|
|
|
case ISD::FROUND: return "fround";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FEXP: return "fexp";
|
|
|
|
case ISD::FEXP2: return "fexp2";
|
|
|
|
case ISD::FLOG: return "flog";
|
|
|
|
case ISD::FLOG2: return "flog2";
|
|
|
|
case ISD::FLOG10: return "flog10";
|
|
|
|
|
|
|
|
// Binary operators
|
|
|
|
case ISD::ADD: return "add";
|
|
|
|
case ISD::SUB: return "sub";
|
|
|
|
case ISD::MUL: return "mul";
|
|
|
|
case ISD::MULHU: return "mulhu";
|
|
|
|
case ISD::MULHS: return "mulhs";
|
|
|
|
case ISD::SDIV: return "sdiv";
|
|
|
|
case ISD::UDIV: return "udiv";
|
|
|
|
case ISD::SREM: return "srem";
|
|
|
|
case ISD::UREM: return "urem";
|
|
|
|
case ISD::SMUL_LOHI: return "smul_lohi";
|
|
|
|
case ISD::UMUL_LOHI: return "umul_lohi";
|
|
|
|
case ISD::SDIVREM: return "sdivrem";
|
|
|
|
case ISD::UDIVREM: return "udivrem";
|
|
|
|
case ISD::AND: return "and";
|
|
|
|
case ISD::OR: return "or";
|
|
|
|
case ISD::XOR: return "xor";
|
|
|
|
case ISD::SHL: return "shl";
|
|
|
|
case ISD::SRA: return "sra";
|
|
|
|
case ISD::SRL: return "srl";
|
|
|
|
case ISD::ROTL: return "rotl";
|
|
|
|
case ISD::ROTR: return "rotr";
|
|
|
|
case ISD::FADD: return "fadd";
|
|
|
|
case ISD::FSUB: return "fsub";
|
|
|
|
case ISD::FMUL: return "fmul";
|
|
|
|
case ISD::FDIV: return "fdiv";
|
|
|
|
case ISD::FMA: return "fma";
|
2015-02-20 23:10:33 +01:00
|
|
|
case ISD::FMAD: return "fmad";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FREM: return "frem";
|
|
|
|
case ISD::FCOPYSIGN: return "fcopysign";
|
|
|
|
case ISD::FGETSIGN: return "fgetsign";
|
2016-04-14 03:42:16 +02:00
|
|
|
case ISD::FCANONICALIZE: return "fcanonicalize";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::FPOW: return "fpow";
|
2015-05-15 11:03:15 +02:00
|
|
|
case ISD::SMIN: return "smin";
|
|
|
|
case ISD::SMAX: return "smax";
|
|
|
|
case ISD::UMIN: return "umin";
|
|
|
|
case ISD::UMAX: return "umax";
|
2012-03-13 06:47:27 +01:00
|
|
|
|
|
|
|
case ISD::FPOWI: return "fpowi";
|
|
|
|
case ISD::SETCC: return "setcc";
|
X86: More efficient legalization of wide integer compares
In particular, this makes the code for 64-bit compares on 32-bit targets
much more efficient.
Example:
define i32 @test_slt(i64 %a, i64 %b) {
entry:
%cmp = icmp slt i64 %a, %b
br i1 %cmp, label %bb1, label %bb2
bb1:
ret i32 1
bb2:
ret i32 2
}
Before this patch:
test_slt:
movl 4(%esp), %eax
movl 8(%esp), %ecx
cmpl 12(%esp), %eax
setae %al
cmpl 16(%esp), %ecx
setge %cl
je .LBB2_2
movb %cl, %al
.LBB2_2:
testb %al, %al
jne .LBB2_4
movl $1, %eax
retl
.LBB2_4:
movl $2, %eax
retl
After this patch:
test_slt:
movl 4(%esp), %eax
movl 8(%esp), %ecx
cmpl 12(%esp), %eax
sbbl 16(%esp), %ecx
jge .LBB1_2
movl $1, %eax
retl
.LBB1_2:
movl $2, %eax
retl
Differential Revision: http://reviews.llvm.org/D14496
llvm-svn: 253572
2015-11-19 17:35:08 +01:00
|
|
|
case ISD::SETCCE: return "setcce";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::SELECT: return "select";
|
|
|
|
case ISD::VSELECT: return "vselect";
|
|
|
|
case ISD::SELECT_CC: return "select_cc";
|
|
|
|
case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt";
|
|
|
|
case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt";
|
|
|
|
case ISD::CONCAT_VECTORS: return "concat_vectors";
|
|
|
|
case ISD::INSERT_SUBVECTOR: return "insert_subvector";
|
|
|
|
case ISD::EXTRACT_SUBVECTOR: return "extract_subvector";
|
|
|
|
case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector";
|
|
|
|
case ISD::VECTOR_SHUFFLE: return "vector_shuffle";
|
|
|
|
case ISD::CARRY_FALSE: return "carry_false";
|
|
|
|
case ISD::ADDC: return "addc";
|
|
|
|
case ISD::ADDE: return "adde";
|
|
|
|
case ISD::SADDO: return "saddo";
|
|
|
|
case ISD::UADDO: return "uaddo";
|
|
|
|
case ISD::SSUBO: return "ssubo";
|
|
|
|
case ISD::USUBO: return "usubo";
|
|
|
|
case ISD::SMULO: return "smulo";
|
|
|
|
case ISD::UMULO: return "umulo";
|
|
|
|
case ISD::SUBC: return "subc";
|
|
|
|
case ISD::SUBE: return "sube";
|
|
|
|
case ISD::SHL_PARTS: return "shl_parts";
|
|
|
|
case ISD::SRA_PARTS: return "sra_parts";
|
|
|
|
case ISD::SRL_PARTS: return "srl_parts";
|
|
|
|
|
|
|
|
// Conversion operators.
|
|
|
|
case ISD::SIGN_EXTEND: return "sign_extend";
|
|
|
|
case ISD::ZERO_EXTEND: return "zero_extend";
|
|
|
|
case ISD::ANY_EXTEND: return "any_extend";
|
|
|
|
case ISD::SIGN_EXTEND_INREG: return "sign_extend_inreg";
|
2014-07-10 14:32:32 +02:00
|
|
|
case ISD::ANY_EXTEND_VECTOR_INREG: return "any_extend_vector_inreg";
|
|
|
|
case ISD::SIGN_EXTEND_VECTOR_INREG: return "sign_extend_vector_inreg";
|
2014-07-09 12:58:18 +02:00
|
|
|
case ISD::ZERO_EXTEND_VECTOR_INREG: return "zero_extend_vector_inreg";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::TRUNCATE: return "truncate";
|
|
|
|
case ISD::FP_ROUND: return "fp_round";
|
|
|
|
case ISD::FLT_ROUNDS_: return "flt_rounds";
|
|
|
|
case ISD::FP_ROUND_INREG: return "fp_round_inreg";
|
|
|
|
case ISD::FP_EXTEND: return "fp_extend";
|
|
|
|
|
|
|
|
case ISD::SINT_TO_FP: return "sint_to_fp";
|
|
|
|
case ISD::UINT_TO_FP: return "uint_to_fp";
|
|
|
|
case ISD::FP_TO_SINT: return "fp_to_sint";
|
|
|
|
case ISD::FP_TO_UINT: return "fp_to_uint";
|
|
|
|
case ISD::BITCAST: return "bitcast";
|
2013-11-15 02:34:59 +01:00
|
|
|
case ISD::ADDRSPACECAST: return "addrspacecast";
|
2014-07-17 12:51:23 +02:00
|
|
|
case ISD::FP16_TO_FP: return "fp16_to_fp";
|
|
|
|
case ISD::FP_TO_FP16: return "fp_to_fp16";
|
2012-03-13 06:47:27 +01:00
|
|
|
|
|
|
|
case ISD::CONVERT_RNDSAT: {
|
|
|
|
switch (cast<CvtRndSatSDNode>(this)->getCvtCode()) {
|
|
|
|
default: llvm_unreachable("Unknown cvt code!");
|
|
|
|
case ISD::CVT_FF: return "cvt_ff";
|
|
|
|
case ISD::CVT_FS: return "cvt_fs";
|
|
|
|
case ISD::CVT_FU: return "cvt_fu";
|
|
|
|
case ISD::CVT_SF: return "cvt_sf";
|
|
|
|
case ISD::CVT_UF: return "cvt_uf";
|
|
|
|
case ISD::CVT_SS: return "cvt_ss";
|
|
|
|
case ISD::CVT_SU: return "cvt_su";
|
|
|
|
case ISD::CVT_US: return "cvt_us";
|
|
|
|
case ISD::CVT_UU: return "cvt_uu";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Control flow instructions
|
|
|
|
case ISD::BR: return "br";
|
|
|
|
case ISD::BRIND: return "brind";
|
|
|
|
case ISD::BR_JT: return "br_jt";
|
|
|
|
case ISD::BRCOND: return "brcond";
|
|
|
|
case ISD::BR_CC: return "br_cc";
|
|
|
|
case ISD::CALLSEQ_START: return "callseq_start";
|
|
|
|
case ISD::CALLSEQ_END: return "callseq_end";
|
|
|
|
|
2015-08-28 01:27:47 +02:00
|
|
|
// EH instructions
|
|
|
|
case ISD::CATCHRET: return "catchret";
|
|
|
|
case ISD::CLEANUPRET: return "cleanupret";
|
|
|
|
|
2012-03-13 06:47:27 +01:00
|
|
|
// Other operators
|
|
|
|
case ISD::LOAD: return "load";
|
|
|
|
case ISD::STORE: return "store";
|
2014-12-04 10:40:44 +01:00
|
|
|
case ISD::MLOAD: return "masked_load";
|
|
|
|
case ISD::MSTORE: return "masked_store";
|
2015-04-30 10:38:48 +02:00
|
|
|
case ISD::MGATHER: return "masked_gather";
|
|
|
|
case ISD::MSCATTER: return "masked_scatter";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::VAARG: return "vaarg";
|
|
|
|
case ISD::VACOPY: return "vacopy";
|
|
|
|
case ISD::VAEND: return "vaend";
|
|
|
|
case ISD::VASTART: return "vastart";
|
|
|
|
case ISD::DYNAMIC_STACKALLOC: return "dynamic_stackalloc";
|
|
|
|
case ISD::EXTRACT_ELEMENT: return "extract_element";
|
|
|
|
case ISD::BUILD_PAIR: return "build_pair";
|
|
|
|
case ISD::STACKSAVE: return "stacksave";
|
|
|
|
case ISD::STACKRESTORE: return "stackrestore";
|
|
|
|
case ISD::TRAP: return "trap";
|
2012-05-14 20:58:10 +02:00
|
|
|
case ISD::DEBUGTRAP: return "debugtrap";
|
2012-09-06 11:17:37 +02:00
|
|
|
case ISD::LIFETIME_START: return "lifetime.start";
|
|
|
|
case ISD::LIFETIME_END: return "lifetime.end";
|
Extend the statepoint intrinsic to allow statepoints to be marked as transitions from GC-aware code to code that is not GC-aware.
This changes the shape of the statepoint intrinsic from:
@llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 unused, ...call args, i32 # deopt args, ...deopt args, ...gc args)
to:
@llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 flags, ...call args, i32 # transition args, ...transition args, i32 # deopt args, ...deopt args, ...gc args)
This extension offers the backend the opportunity to insert (somewhat) arbitrary code to manage the transition from GC-aware code to code that is not GC-aware and back.
In order to support the injection of transition code, this extension wraps the STATEPOINT ISD node generated by the usual lowering lowering with two additional nodes: GC_TRANSITION_START and GC_TRANSITION_END. The transition arguments that were passed passed to the intrinsic (if any) are lowered and provided as operands to these nodes and may be used by the backend during code generation.
Eventually, the lowering of the GC_TRANSITION_{START,END} nodes should be informed by the GC strategy in use for the function containing the intrinsic call; for now, these nodes are instead replaced with no-ops.
Differential Revision: http://reviews.llvm.org/D9501
llvm-svn: 236888
2015-05-08 20:07:42 +02:00
|
|
|
case ISD::GC_TRANSITION_START: return "gc_transition.start";
|
|
|
|
case ISD::GC_TRANSITION_END: return "gc_transition.end";
|
2015-12-01 12:40:55 +01:00
|
|
|
case ISD::GET_DYNAMIC_AREA_OFFSET: return "get.dynamic.area.offset";
|
2012-03-13 06:47:27 +01:00
|
|
|
|
|
|
|
// Bit manipulation
|
2015-11-12 13:29:09 +01:00
|
|
|
case ISD::BITREVERSE: return "bitreverse";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::BSWAP: return "bswap";
|
|
|
|
case ISD::CTPOP: return "ctpop";
|
|
|
|
case ISD::CTTZ: return "cttz";
|
|
|
|
case ISD::CTTZ_ZERO_UNDEF: return "cttz_zero_undef";
|
|
|
|
case ISD::CTLZ: return "ctlz";
|
|
|
|
case ISD::CTLZ_ZERO_UNDEF: return "ctlz_zero_undef";
|
2015-11-12 13:29:09 +01:00
|
|
|
|
2012-03-13 06:47:27 +01:00
|
|
|
// Trampolines
|
|
|
|
case ISD::INIT_TRAMPOLINE: return "init_trampoline";
|
|
|
|
case ISD::ADJUST_TRAMPOLINE: return "adjust_trampoline";
|
|
|
|
|
|
|
|
case ISD::CONDCODE:
|
|
|
|
switch (cast<CondCodeSDNode>(this)->get()) {
|
|
|
|
default: llvm_unreachable("Unknown setcc condition!");
|
|
|
|
case ISD::SETOEQ: return "setoeq";
|
|
|
|
case ISD::SETOGT: return "setogt";
|
|
|
|
case ISD::SETOGE: return "setoge";
|
|
|
|
case ISD::SETOLT: return "setolt";
|
|
|
|
case ISD::SETOLE: return "setole";
|
|
|
|
case ISD::SETONE: return "setone";
|
|
|
|
|
|
|
|
case ISD::SETO: return "seto";
|
|
|
|
case ISD::SETUO: return "setuo";
|
2015-08-11 23:10:07 +02:00
|
|
|
case ISD::SETUEQ: return "setueq";
|
2012-03-13 06:47:27 +01:00
|
|
|
case ISD::SETUGT: return "setugt";
|
|
|
|
case ISD::SETUGE: return "setuge";
|
|
|
|
case ISD::SETULT: return "setult";
|
|
|
|
case ISD::SETULE: return "setule";
|
|
|
|
case ISD::SETUNE: return "setune";
|
|
|
|
|
|
|
|
case ISD::SETEQ: return "seteq";
|
|
|
|
case ISD::SETGT: return "setgt";
|
|
|
|
case ISD::SETGE: return "setge";
|
|
|
|
case ISD::SETLT: return "setlt";
|
|
|
|
case ISD::SETLE: return "setle";
|
|
|
|
case ISD::SETNE: return "setne";
|
|
|
|
|
|
|
|
case ISD::SETTRUE: return "settrue";
|
|
|
|
case ISD::SETTRUE2: return "settrue2";
|
|
|
|
case ISD::SETFALSE: return "setfalse";
|
|
|
|
case ISD::SETFALSE2: return "setfalse2";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *SDNode::getIndexedModeName(ISD::MemIndexedMode AM) {
|
|
|
|
switch (AM) {
|
|
|
|
default: return "";
|
|
|
|
case ISD::PRE_INC: return "<pre-inc>";
|
|
|
|
case ISD::PRE_DEC: return "<pre-dec>";
|
|
|
|
case ISD::POST_INC: return "<post-inc>";
|
|
|
|
case ISD::POST_DEC: return "<post-dec>";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-04 02:31:59 +01:00
|
|
|
static Printable PrintNodeId(const SDNode &Node) {
|
|
|
|
return Printable([&Node](raw_ostream &OS) {
|
SelectionDAG: Introduce PersistentID to SDNode for assert builds.
This gives us more human readable numbers to identify nodes in debug
dumps.
Before:
0x7fcbd9700160: ch = EntryToken
0x7fcbd985c7c8: i64 = Register %RAX
...
0x7fcbd9700160: <multiple use>
0x7fcbd985c578: i64,ch = MOV64rm 0x7fcbd985c6a0, 0x7fcbd985cc68, 0x7fcbd985c200, 0x7fcbd985cd90, 0x7fcbd985ceb8, 0x7fcbd9700160<Mem:LD8[@foo]> [ORD=2]
0x7fcbd985c8f0: ch,glue = CopyToReg 0x7fcbd9700160, 0x7fcbd985c7c8, 0x7fcbd985c578 [ORD=3]
0x7fcbd985c7c8: <multiple use>
0x7fcbd985c8f0: <multiple use>
0x7fcbd985c8f0: <multiple use>
0x7fcbd985ca18: ch = RETQ 0x7fcbd985c7c8, 0x7fcbd985c8f0, 0x7fcbd985c8f0:1 [ORD=3]
Now:
t0: ch = EntryToken
t5: i64 = Register %RAX
...
t0: <multiple use>
t3: i64,ch = MOV64rm t10, t12, t11, t13, t14, t0<Mem:LD8[@foo]> [ORD=2]
t6: ch,glue = CopyToReg t0, t5, t3 [ORD=3]
t5: <multiple use>
t6: <multiple use>
t6: <multiple use>
t7: ch = RETQ t5, t6, t6:1 [ORD=3]
Differential Revision: http://reviews.llvm.org/D12564
llvm-svn: 248010
2015-09-18 19:41:00 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
OS << 't' << Node.PersistentId;
|
|
|
|
#else
|
|
|
|
OS << (const void*)&Node;
|
|
|
|
#endif
|
2015-12-04 02:31:59 +01:00
|
|
|
});
|
SelectionDAG: Introduce PersistentID to SDNode for assert builds.
This gives us more human readable numbers to identify nodes in debug
dumps.
Before:
0x7fcbd9700160: ch = EntryToken
0x7fcbd985c7c8: i64 = Register %RAX
...
0x7fcbd9700160: <multiple use>
0x7fcbd985c578: i64,ch = MOV64rm 0x7fcbd985c6a0, 0x7fcbd985cc68, 0x7fcbd985c200, 0x7fcbd985cd90, 0x7fcbd985ceb8, 0x7fcbd9700160<Mem:LD8[@foo]> [ORD=2]
0x7fcbd985c8f0: ch,glue = CopyToReg 0x7fcbd9700160, 0x7fcbd985c7c8, 0x7fcbd985c578 [ORD=3]
0x7fcbd985c7c8: <multiple use>
0x7fcbd985c8f0: <multiple use>
0x7fcbd985c8f0: <multiple use>
0x7fcbd985ca18: ch = RETQ 0x7fcbd985c7c8, 0x7fcbd985c8f0, 0x7fcbd985c8f0:1 [ORD=3]
Now:
t0: ch = EntryToken
t5: i64 = Register %RAX
...
t0: <multiple use>
t3: i64,ch = MOV64rm t10, t12, t11, t13, t14, t0<Mem:LD8[@foo]> [ORD=2]
t6: ch,glue = CopyToReg t0, t5, t3 [ORD=3]
t5: <multiple use>
t6: <multiple use>
t6: <multiple use>
t7: ch = RETQ t5, t6, t6:1 [ORD=3]
Differential Revision: http://reviews.llvm.org/D12564
llvm-svn: 248010
2015-09-18 19:41:00 +02:00
|
|
|
}
|
|
|
|
|
2016-01-29 21:50:44 +01:00
|
|
|
LLVM_DUMP_METHOD void SDNode::dump() const { dump(nullptr); }
|
2012-03-13 06:47:27 +01:00
|
|
|
void SDNode::dump(const SelectionDAG *G) const {
|
|
|
|
print(dbgs(), G);
|
|
|
|
dbgs() << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::print_types(raw_ostream &OS, const SelectionDAG *G) const {
|
|
|
|
for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
|
|
|
|
if (i) OS << ",";
|
|
|
|
if (getValueType(i) == MVT::Other)
|
|
|
|
OS << "ch";
|
|
|
|
else
|
|
|
|
OS << getValueType(i).getEVTString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
|
|
|
|
if (const MachineSDNode *MN = dyn_cast<MachineSDNode>(this)) {
|
|
|
|
if (!MN->memoperands_empty()) {
|
|
|
|
OS << "<";
|
|
|
|
OS << "Mem:";
|
|
|
|
for (MachineSDNode::mmo_iterator i = MN->memoperands_begin(),
|
|
|
|
e = MN->memoperands_end(); i != e; ++i) {
|
|
|
|
OS << **i;
|
2014-03-02 13:27:27 +01:00
|
|
|
if (std::next(i) != e)
|
2012-03-13 06:47:27 +01:00
|
|
|
OS << " ";
|
|
|
|
}
|
|
|
|
OS << ">";
|
|
|
|
}
|
|
|
|
} else if (const ShuffleVectorSDNode *SVN =
|
|
|
|
dyn_cast<ShuffleVectorSDNode>(this)) {
|
|
|
|
OS << "<";
|
|
|
|
for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) {
|
|
|
|
int Idx = SVN->getMaskElt(i);
|
|
|
|
if (i) OS << ",";
|
|
|
|
if (Idx < 0)
|
|
|
|
OS << "u";
|
|
|
|
else
|
|
|
|
OS << Idx;
|
|
|
|
}
|
|
|
|
OS << ">";
|
|
|
|
} else if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(this)) {
|
|
|
|
OS << '<' << CSDN->getAPIntValue() << '>';
|
|
|
|
} else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(this)) {
|
|
|
|
if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle)
|
|
|
|
OS << '<' << CSDN->getValueAPF().convertToFloat() << '>';
|
|
|
|
else if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEdouble)
|
|
|
|
OS << '<' << CSDN->getValueAPF().convertToDouble() << '>';
|
|
|
|
else {
|
|
|
|
OS << "<APFloat(";
|
|
|
|
CSDN->getValueAPF().bitcastToAPInt().dump();
|
|
|
|
OS << ")>";
|
|
|
|
}
|
|
|
|
} else if (const GlobalAddressSDNode *GADN =
|
|
|
|
dyn_cast<GlobalAddressSDNode>(this)) {
|
|
|
|
int64_t offset = GADN->getOffset();
|
|
|
|
OS << '<';
|
2014-01-09 03:29:41 +01:00
|
|
|
GADN->getGlobal()->printAsOperand(OS);
|
2012-03-13 06:47:27 +01:00
|
|
|
OS << '>';
|
|
|
|
if (offset > 0)
|
|
|
|
OS << " + " << offset;
|
|
|
|
else
|
|
|
|
OS << " " << offset;
|
|
|
|
if (unsigned int TF = GADN->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
|
|
|
} else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(this)) {
|
|
|
|
OS << "<" << FIDN->getIndex() << ">";
|
|
|
|
} else if (const JumpTableSDNode *JTDN = dyn_cast<JumpTableSDNode>(this)) {
|
|
|
|
OS << "<" << JTDN->getIndex() << ">";
|
|
|
|
if (unsigned int TF = JTDN->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
|
|
|
} else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(this)){
|
|
|
|
int offset = CP->getOffset();
|
|
|
|
if (CP->isMachineConstantPoolEntry())
|
|
|
|
OS << "<" << *CP->getMachineCPVal() << ">";
|
|
|
|
else
|
|
|
|
OS << "<" << *CP->getConstVal() << ">";
|
|
|
|
if (offset > 0)
|
|
|
|
OS << " + " << offset;
|
|
|
|
else
|
|
|
|
OS << " " << offset;
|
|
|
|
if (unsigned int TF = CP->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
2012-08-08 00:37:05 +02:00
|
|
|
} else if (const TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(this)) {
|
|
|
|
OS << "<" << TI->getIndex() << '+' << TI->getOffset() << ">";
|
|
|
|
if (unsigned TF = TI->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
2012-03-13 06:47:27 +01:00
|
|
|
} else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(this)) {
|
|
|
|
OS << "<";
|
|
|
|
const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
|
|
|
|
if (LBB)
|
|
|
|
OS << LBB->getName() << " ";
|
|
|
|
OS << (const void*)BBDN->getBasicBlock() << ">";
|
|
|
|
} else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(this)) {
|
2014-08-05 04:39:49 +02:00
|
|
|
OS << ' ' << PrintReg(R->getReg(),
|
|
|
|
G ? G->getSubtarget().getRegisterInfo() : nullptr);
|
2012-03-13 06:47:27 +01:00
|
|
|
} else if (const ExternalSymbolSDNode *ES =
|
|
|
|
dyn_cast<ExternalSymbolSDNode>(this)) {
|
|
|
|
OS << "'" << ES->getSymbol() << "'";
|
|
|
|
if (unsigned int TF = ES->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
|
|
|
} else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(this)) {
|
|
|
|
if (M->getValue())
|
|
|
|
OS << "<" << M->getValue() << ">";
|
|
|
|
else
|
|
|
|
OS << "<null>";
|
|
|
|
} else if (const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(this)) {
|
|
|
|
if (MD->getMD())
|
|
|
|
OS << "<" << MD->getMD() << ">";
|
|
|
|
else
|
|
|
|
OS << "<null>";
|
|
|
|
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
|
|
|
|
OS << ":" << N->getVT().getEVTString();
|
|
|
|
}
|
|
|
|
else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) {
|
|
|
|
OS << "<" << *LD->getMemOperand();
|
|
|
|
|
|
|
|
bool doExt = true;
|
|
|
|
switch (LD->getExtensionType()) {
|
|
|
|
default: doExt = false; break;
|
|
|
|
case ISD::EXTLOAD: OS << ", anyext"; break;
|
|
|
|
case ISD::SEXTLOAD: OS << ", sext"; break;
|
|
|
|
case ISD::ZEXTLOAD: OS << ", zext"; break;
|
|
|
|
}
|
|
|
|
if (doExt)
|
|
|
|
OS << " from " << LD->getMemoryVT().getEVTString();
|
|
|
|
|
|
|
|
const char *AM = getIndexedModeName(LD->getAddressingMode());
|
|
|
|
if (*AM)
|
|
|
|
OS << ", " << AM;
|
|
|
|
|
|
|
|
OS << ">";
|
|
|
|
} else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(this)) {
|
|
|
|
OS << "<" << *ST->getMemOperand();
|
|
|
|
|
|
|
|
if (ST->isTruncatingStore())
|
|
|
|
OS << ", trunc to " << ST->getMemoryVT().getEVTString();
|
|
|
|
|
|
|
|
const char *AM = getIndexedModeName(ST->getAddressingMode());
|
|
|
|
if (*AM)
|
|
|
|
OS << ", " << AM;
|
|
|
|
|
|
|
|
OS << ">";
|
|
|
|
} else if (const MemSDNode* M = dyn_cast<MemSDNode>(this)) {
|
|
|
|
OS << "<" << *M->getMemOperand() << ">";
|
|
|
|
} else if (const BlockAddressSDNode *BA =
|
|
|
|
dyn_cast<BlockAddressSDNode>(this)) {
|
2012-09-12 23:43:09 +02:00
|
|
|
int64_t offset = BA->getOffset();
|
2012-03-13 06:47:27 +01:00
|
|
|
OS << "<";
|
2014-01-09 03:29:41 +01:00
|
|
|
BA->getBlockAddress()->getFunction()->printAsOperand(OS, false);
|
2012-03-13 06:47:27 +01:00
|
|
|
OS << ", ";
|
2014-01-09 03:29:41 +01:00
|
|
|
BA->getBlockAddress()->getBasicBlock()->printAsOperand(OS, false);
|
2012-03-13 06:47:27 +01:00
|
|
|
OS << ">";
|
2012-09-12 23:43:09 +02:00
|
|
|
if (offset > 0)
|
|
|
|
OS << " + " << offset;
|
|
|
|
else
|
|
|
|
OS << " " << offset;
|
2012-03-13 06:47:27 +01:00
|
|
|
if (unsigned int TF = BA->getTargetFlags())
|
|
|
|
OS << " [TF=" << TF << ']';
|
2013-11-15 02:34:59 +01:00
|
|
|
} else if (const AddrSpaceCastSDNode *ASC =
|
|
|
|
dyn_cast<AddrSpaceCastSDNode>(this)) {
|
|
|
|
OS << '['
|
|
|
|
<< ASC->getSrcAddressSpace()
|
|
|
|
<< " -> "
|
|
|
|
<< ASC->getDestAddressSpace()
|
|
|
|
<< ']';
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
if (VerboseDAGDumping) {
|
|
|
|
if (unsigned Order = getIROrder())
|
|
|
|
OS << " [ORD=" << Order << ']';
|
2012-03-13 06:47:27 +01:00
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
if (getNodeId() != -1)
|
|
|
|
OS << " [ID=" << getNodeId() << ']';
|
2012-03-13 06:47:27 +01:00
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
if (!G)
|
|
|
|
return;
|
2015-03-30 20:23:28 +02:00
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
DILocation *L = getDebugLoc();
|
|
|
|
if (!L)
|
|
|
|
return;
|
2015-03-30 20:23:28 +02:00
|
|
|
|
2015-09-18 19:57:28 +02:00
|
|
|
if (auto *Scope = L->getScope())
|
|
|
|
OS << Scope->getFilename();
|
|
|
|
else
|
|
|
|
OS << "<unknown>";
|
|
|
|
OS << ':' << L->getLine();
|
|
|
|
if (unsigned C = L->getColumn())
|
|
|
|
OS << ':' << C;
|
|
|
|
}
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
/// Return true if this node is so simple that we should just print it inline
|
|
|
|
/// if it appears as an operand.
|
|
|
|
static bool shouldPrintInline(const SDNode &Node) {
|
|
|
|
if (Node.getOpcode() == ISD::EntryToken)
|
|
|
|
return false;
|
|
|
|
return Node.getNumOperands() == 0;
|
|
|
|
}
|
|
|
|
|
2012-03-13 06:47:27 +01:00
|
|
|
static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) {
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
for (const SDValue &Op : N->op_values()) {
|
|
|
|
if (shouldPrintInline(*Op.getNode()))
|
|
|
|
continue;
|
2015-06-26 21:37:02 +02:00
|
|
|
if (Op.getNode()->hasOneUse())
|
|
|
|
DumpNodes(Op.getNode(), indent+2, G);
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
}
|
2012-03-13 06:47:27 +01:00
|
|
|
|
|
|
|
dbgs().indent(indent);
|
|
|
|
N->dump(G);
|
|
|
|
}
|
|
|
|
|
2016-01-29 21:50:44 +01:00
|
|
|
LLVM_DUMP_METHOD void SelectionDAG::dump() const {
|
SelectionDAGDumper: Avoid unnecessary newlines
Before:
t0 = EntryToken:ch
t0: <multiple use>
t0: <multiple use>
t1 = CopyFromReg:v4f32,ch t0, Register:v4f32 %vreg0
t25 = IMPLICIT_DEF:v4f32
t26 = HADDPSrr:v4f32 t1, t25
t23 = CopyToReg:ch,glue t0, Register:v4f32 %XMM0, t26
t23: <multiple use>
t23: <multiple use>
t24 = RETQ:ch Register:v4f32 %XMM0, t23, t23:1
After:
t0: <multiple use>
t0: <multiple use>
t1 = CopyFromReg:v4f32,ch t0, Register:v4f32 %vreg0
t26 = X86ISD::FHADD:v4f32 t1, undef:v4f32
t23 = CopyToReg:ch,glue t0, Register:v4f32 %XMM0, t26
t23: <multiple use>
t21 = TargetConstant:i16<0>
t23: <multiple use>
t24 = X86ISD::RET_FLAG:ch t23, t21, Register:v4f32 %XMM0, t23:1
Differential Revision: http://reviews.llvm.org/D12568
llvm-svn: 248012
2015-09-18 19:57:31 +02:00
|
|
|
dbgs() << "SelectionDAG has " << AllNodes.size() << " nodes:\n";
|
2012-03-13 06:47:27 +01:00
|
|
|
|
|
|
|
for (allnodes_const_iterator I = allnodes_begin(), E = allnodes_end();
|
|
|
|
I != E; ++I) {
|
2015-10-13 21:47:46 +02:00
|
|
|
const SDNode *N = &*I;
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
if (!N->hasOneUse() && N != getRoot().getNode() &&
|
|
|
|
(!shouldPrintInline(*N) || N->use_empty()))
|
2012-03-13 06:47:27 +01:00
|
|
|
DumpNodes(N, 2, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getRoot().getNode()) DumpNodes(getRoot().getNode(), 2, this);
|
|
|
|
dbgs() << "\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const {
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
OS << PrintNodeId(*this) << ": ";
|
2012-03-13 06:47:27 +01:00
|
|
|
print_types(OS, G);
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
OS << " = " << getOperationName(G);
|
2012-03-13 06:47:27 +01:00
|
|
|
print_details(OS, G);
|
|
|
|
}
|
|
|
|
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
static bool printOperand(raw_ostream &OS, const SelectionDAG *G,
|
|
|
|
const SDValue Value) {
|
[X86] Part 1 to fix x86-64 fp128 calling convention.
Almost all these changes are conditioned and only apply to the new
x86-64 f128 type configuration, which will be enabled in a follow up
patch. They are required together to make new f128 work. If there is
any error, we should fix or revert them as a whole.
These changes should have no impact to current configurations.
* Relax type legalization checks to accept new f128 type configuration,
whose TypeAction is TypeSoftenFloat, not TypeLegal, but also has
TLI.isTypeLegal true.
* Relax GetSoftenedFloat to return in some cases f128 type SDValue,
which is TLI.isTypeLegal but not "softened" to i128 node.
* Allow customized FABS, FNEG, FCOPYSIGN on new f128 type configuration,
to generate optimized bitwise operators for libm functions.
* Enhance related Lower* functions to handle f128 type.
* Enhance DAGTypeLegalizer::run, SoftenFloatResult, and related functions
to keep new f128 type in register, and convert f128 operators to library calls.
* Fix Combiner, Emitter, Legalizer routines that did not handle f128 type.
* Add ExpandConstant to handle i128 constants, ExpandNode
to handle ISD::Constant node.
* Add one more parameter to getCommonSubClass and firstCommonClass,
to guarantee that returned common sub class will contain the specified
simple value type.
This extra parameter is used by EmitCopyFromReg in InstrEmitter.cpp.
* Fix infinite loop in getTypeLegalizationCost when f128 is the value type.
* Fix printOperand to handle null operand.
* Enhance ISD::BITCAST node to handle f128 constant.
* Expand new f128 type for BR_CC, SELECT_CC, SELECT, SETCC nodes.
* Enhance X86AsmPrinter to emit f128 values in comments.
Differential Revision: http://reviews.llvm.org/D15134
llvm-svn: 254653
2015-12-03 23:02:40 +01:00
|
|
|
if (!Value.getNode()) {
|
|
|
|
OS << "<null>";
|
|
|
|
return false;
|
|
|
|
} else if (shouldPrintInline(*Value.getNode())) {
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
OS << Value->getOperationName(G) << ':';
|
|
|
|
Value->print_types(OS, G);
|
|
|
|
Value->print_details(OS, G);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
OS << PrintNodeId(*Value.getNode());
|
|
|
|
if (unsigned RN = Value.getResNo())
|
|
|
|
OS << ':' << RN;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-30 02:24:31 +01:00
|
|
|
typedef SmallPtrSet<const SDNode *, 32> VisitedSDNodeSet;
|
2012-03-13 06:47:27 +01:00
|
|
|
static void DumpNodesr(raw_ostream &OS, const SDNode *N, unsigned indent,
|
|
|
|
const SelectionDAG *G, VisitedSDNodeSet &once) {
|
2014-11-19 08:49:26 +01:00
|
|
|
if (!once.insert(N).second) // If we've been here before, return now.
|
2012-03-13 06:47:27 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Dump the current SDNode, but don't end the line yet.
|
|
|
|
OS.indent(indent);
|
|
|
|
N->printr(OS, G);
|
|
|
|
|
|
|
|
// Having printed this SDNode, walk the children:
|
|
|
|
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
|
|
|
|
if (i) OS << ",";
|
|
|
|
OS << " ";
|
|
|
|
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
const SDValue Op = N->getOperand(i);
|
|
|
|
bool printedInline = printOperand(OS, G, Op);
|
|
|
|
if (printedInline)
|
|
|
|
once.insert(Op.getNode());
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
OS << "\n";
|
|
|
|
|
|
|
|
// Dump children that have grandchildren on their own line(s).
|
2015-06-26 21:37:02 +02:00
|
|
|
for (const SDValue &Op : N->op_values())
|
|
|
|
DumpNodesr(OS, Op.getNode(), indent+2, G, once);
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::dumpr() const {
|
|
|
|
VisitedSDNodeSet once;
|
2014-04-14 02:51:57 +02:00
|
|
|
DumpNodesr(dbgs(), this, 0, nullptr, once);
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::dumpr(const SelectionDAG *G) const {
|
|
|
|
VisitedSDNodeSet once;
|
|
|
|
DumpNodesr(dbgs(), this, 0, G, once);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N,
|
|
|
|
const SelectionDAG *G, unsigned depth,
|
|
|
|
unsigned indent) {
|
|
|
|
if (depth == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
OS.indent(indent);
|
|
|
|
|
|
|
|
N->print(OS, G);
|
|
|
|
|
|
|
|
if (depth < 1)
|
|
|
|
return;
|
|
|
|
|
2015-06-26 21:37:02 +02:00
|
|
|
for (const SDValue &Op : N->op_values()) {
|
2012-03-13 06:47:27 +01:00
|
|
|
// Don't follow chain operands.
|
2015-06-26 21:37:02 +02:00
|
|
|
if (Op.getValueType() == MVT::Other)
|
2012-03-13 06:47:27 +01:00
|
|
|
continue;
|
|
|
|
OS << '\n';
|
2015-06-26 21:37:02 +02:00
|
|
|
printrWithDepthHelper(OS, Op.getNode(), G, depth-1, indent+2);
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::printrWithDepth(raw_ostream &OS, const SelectionDAG *G,
|
|
|
|
unsigned depth) const {
|
|
|
|
printrWithDepthHelper(OS, this, G, depth, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::printrFull(raw_ostream &OS, const SelectionDAG *G) const {
|
|
|
|
// Don't print impossibly deep things.
|
|
|
|
printrWithDepth(OS, G, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const {
|
|
|
|
printrWithDepth(dbgs(), G, depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::dumprFull(const SelectionDAG *G) const {
|
|
|
|
// Don't print impossibly deep things.
|
|
|
|
dumprWithDepth(G, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
printr(OS, G);
|
2012-03-13 06:47:27 +01:00
|
|
|
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
|
|
|
if (i) OS << ", "; else OS << " ";
|
SelectionDAGDumper: Print simple operands inline.
Print simple operands inline instead of their pointer/value number.
Simple operands are SDNodes without predecessors like Constant(FP), Register,
UNDEF. This unifies the behaviour with dumpr() which was already doing this.
Previously:
t0: ch = EntryToken
t1: i64 = Register %vreg0
t2: i64,ch = CopyFromReg t0, t1
t3: i64 = Constant<1>
t4: i64 = add t2, t3
t5: i64 = Constant<2>
t6: i64 = add t2, t5
t10: i64 = undef
t11: i8,ch = load t0, t2, t10<LD1[%tmp81]>
t12: i8,ch = load t0, t4, t10<LD1[%tmp10]>
t13: i8,ch = load t0, t6, t10<LD1[%tmp12]>
Now:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t4: i64 = add t2, Constant:i64<1>
t6: i64 = add t2, Constant:i64<2>
t11: i8,ch = load<LD1[%tmp81]> t0, t2, undef:i64
t12: i8,ch = load<LD1[%tmp10]> t0, t4, undef:i64
t13: i8,ch = load<LD1[%tmp12]> t0, t6, undef:i64
Differential Revision: http://reviews.llvm.org/D12567
llvm-svn: 248628
2015-09-26 00:27:02 +02:00
|
|
|
printOperand(OS, G, getOperand(i));
|
2012-03-13 06:47:27 +01:00
|
|
|
}
|
|
|
|
}
|