2005-01-07 07:44:53 +00:00
|
|
|
//===-- TargetLowering.cpp - Implement the TargetLowering class -----------===//
|
2005-04-21 22:55:34 +00:00
|
|
|
//
|
2005-01-07 07:44:53 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-21 22:55:34 +00:00
|
|
|
//
|
2005-01-07 07:44:53 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This implements the TargetLowering class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-02-26 02:33:44 +00:00
|
|
|
#include "llvm/Target/TargetAsmInfo.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
#include "llvm/Target/TargetLowering.h"
|
2007-11-05 23:12:20 +00:00
|
|
|
#include "llvm/Target/TargetSubtarget.h"
|
2006-05-12 06:33:49 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2008-02-10 18:45:23 +00:00
|
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
Drop ISD::MEMSET, ISD::MEMMOVE, and ISD::MEMCPY, which are not Legal
on any current target and aren't optimized in DAGCombiner. Instead
of using intermediate nodes, expand the operations, choosing between
simple loads/stores, target-specific code, and library calls,
immediately.
Previously, the code to emit optimized code for these operations
was only used at initial SelectionDAG construction time; now it is
used at all times. This fixes some cases where rep;movs was being
used for small copies where simple loads/stores would be better.
This also cleans up code that checks for alignments less than 4;
let the targets make that decision instead of doing it in
target-independent code. This allows x86 to use rep;movs in
low-alignment cases.
Also, this fixes a bug that resulted in the use of rep;stos for
memsets of 0 with non-constant memory size when the alignment was
at least 4. It's better to use the library in this case, which
can be significantly faster when the size is large.
This also preserves more SourceValue information when memory
intrinsics are lowered into simple loads/stores.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49572 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-12 04:36:06 +00:00
|
|
|
#include "llvm/GlobalVariable.h"
|
2006-03-31 00:28:56 +00:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2008-05-12 19:56:52 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2006-01-26 20:37:03 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2007-09-07 04:06:50 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2006-01-30 04:09:27 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2007-01-12 02:11:51 +00:00
|
|
|
/// InitLibcallNames - Set default libcall names.
|
|
|
|
///
|
2007-01-12 22:51:10 +00:00
|
|
|
static void InitLibcallNames(const char **Names) {
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SHL_I32] = "__ashlsi3";
|
|
|
|
Names[RTLIB::SHL_I64] = "__ashldi3";
|
2008-07-11 16:52:29 +00:00
|
|
|
Names[RTLIB::SHL_I128] = "__ashlti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SRL_I32] = "__lshrsi3";
|
|
|
|
Names[RTLIB::SRL_I64] = "__lshrdi3";
|
2008-07-11 16:52:29 +00:00
|
|
|
Names[RTLIB::SRL_I128] = "__lshrti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SRA_I32] = "__ashrsi3";
|
|
|
|
Names[RTLIB::SRA_I64] = "__ashrdi3";
|
2008-07-11 16:52:29 +00:00
|
|
|
Names[RTLIB::SRA_I128] = "__ashrti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::MUL_I32] = "__mulsi3";
|
|
|
|
Names[RTLIB::MUL_I64] = "__muldi3";
|
2008-07-10 15:35:05 +00:00
|
|
|
Names[RTLIB::MUL_I128] = "__multi3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SDIV_I32] = "__divsi3";
|
|
|
|
Names[RTLIB::SDIV_I64] = "__divdi3";
|
2008-07-10 15:35:05 +00:00
|
|
|
Names[RTLIB::SDIV_I128] = "__divti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::UDIV_I32] = "__udivsi3";
|
|
|
|
Names[RTLIB::UDIV_I64] = "__udivdi3";
|
2008-07-10 15:35:05 +00:00
|
|
|
Names[RTLIB::UDIV_I128] = "__udivti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SREM_I32] = "__modsi3";
|
|
|
|
Names[RTLIB::SREM_I64] = "__moddi3";
|
2008-07-10 15:35:05 +00:00
|
|
|
Names[RTLIB::SREM_I128] = "__modti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::UREM_I32] = "__umodsi3";
|
|
|
|
Names[RTLIB::UREM_I64] = "__umoddi3";
|
2008-07-10 15:35:05 +00:00
|
|
|
Names[RTLIB::UREM_I128] = "__umodti3";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::NEG_I32] = "__negsi2";
|
|
|
|
Names[RTLIB::NEG_I64] = "__negdi2";
|
|
|
|
Names[RTLIB::ADD_F32] = "__addsf3";
|
|
|
|
Names[RTLIB::ADD_F64] = "__adddf3";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::ADD_F80] = "__addxf3";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::ADD_PPCF128] = "__gcc_qadd";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SUB_F32] = "__subsf3";
|
|
|
|
Names[RTLIB::SUB_F64] = "__subdf3";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::SUB_F80] = "__subxf3";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::SUB_PPCF128] = "__gcc_qsub";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::MUL_F32] = "__mulsf3";
|
|
|
|
Names[RTLIB::MUL_F64] = "__muldf3";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::MUL_F80] = "__mulxf3";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::MUL_PPCF128] = "__gcc_qmul";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::DIV_F32] = "__divsf3";
|
|
|
|
Names[RTLIB::DIV_F64] = "__divdf3";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::DIV_F80] = "__divxf3";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::DIV_PPCF128] = "__gcc_qdiv";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::REM_F32] = "fmodf";
|
|
|
|
Names[RTLIB::REM_F64] = "fmod";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::REM_F80] = "fmodl";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::REM_PPCF128] = "fmodl";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::POWI_F32] = "__powisf2";
|
|
|
|
Names[RTLIB::POWI_F64] = "__powidf2";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::POWI_F80] = "__powixf2";
|
|
|
|
Names[RTLIB::POWI_PPCF128] = "__powitf2";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SQRT_F32] = "sqrtf";
|
|
|
|
Names[RTLIB::SQRT_F64] = "sqrt";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::SQRT_F80] = "sqrtl";
|
|
|
|
Names[RTLIB::SQRT_PPCF128] = "sqrtl";
|
2008-09-04 00:47:13 +00:00
|
|
|
Names[RTLIB::LOG_F32] = "logf";
|
|
|
|
Names[RTLIB::LOG_F64] = "log";
|
|
|
|
Names[RTLIB::LOG_F80] = "logl";
|
|
|
|
Names[RTLIB::LOG_PPCF128] = "logl";
|
|
|
|
Names[RTLIB::LOG2_F32] = "log2f";
|
|
|
|
Names[RTLIB::LOG2_F64] = "log2";
|
|
|
|
Names[RTLIB::LOG2_F80] = "log2l";
|
|
|
|
Names[RTLIB::LOG2_PPCF128] = "log2l";
|
|
|
|
Names[RTLIB::LOG10_F32] = "log10f";
|
|
|
|
Names[RTLIB::LOG10_F64] = "log10";
|
|
|
|
Names[RTLIB::LOG10_F80] = "log10l";
|
|
|
|
Names[RTLIB::LOG10_PPCF128] = "log10l";
|
|
|
|
Names[RTLIB::EXP_F32] = "expf";
|
|
|
|
Names[RTLIB::EXP_F64] = "exp";
|
|
|
|
Names[RTLIB::EXP_F80] = "expl";
|
|
|
|
Names[RTLIB::EXP_PPCF128] = "expl";
|
|
|
|
Names[RTLIB::EXP2_F32] = "exp2f";
|
|
|
|
Names[RTLIB::EXP2_F64] = "exp2";
|
|
|
|
Names[RTLIB::EXP2_F80] = "exp2l";
|
|
|
|
Names[RTLIB::EXP2_PPCF128] = "exp2l";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SIN_F32] = "sinf";
|
|
|
|
Names[RTLIB::SIN_F64] = "sin";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::SIN_F80] = "sinl";
|
|
|
|
Names[RTLIB::SIN_PPCF128] = "sinl";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::COS_F32] = "cosf";
|
|
|
|
Names[RTLIB::COS_F64] = "cos";
|
2008-01-10 10:28:30 +00:00
|
|
|
Names[RTLIB::COS_F80] = "cosl";
|
|
|
|
Names[RTLIB::COS_PPCF128] = "cosl";
|
2007-10-11 23:09:10 +00:00
|
|
|
Names[RTLIB::POW_F32] = "powf";
|
|
|
|
Names[RTLIB::POW_F64] = "pow";
|
|
|
|
Names[RTLIB::POW_F80] = "powl";
|
|
|
|
Names[RTLIB::POW_PPCF128] = "powl";
|
2008-08-21 18:38:14 +00:00
|
|
|
Names[RTLIB::CEIL_F32] = "ceilf";
|
|
|
|
Names[RTLIB::CEIL_F64] = "ceil";
|
|
|
|
Names[RTLIB::CEIL_F80] = "ceill";
|
|
|
|
Names[RTLIB::CEIL_PPCF128] = "ceill";
|
|
|
|
Names[RTLIB::TRUNC_F32] = "truncf";
|
|
|
|
Names[RTLIB::TRUNC_F64] = "trunc";
|
|
|
|
Names[RTLIB::TRUNC_F80] = "truncl";
|
|
|
|
Names[RTLIB::TRUNC_PPCF128] = "truncl";
|
|
|
|
Names[RTLIB::RINT_F32] = "rintf";
|
|
|
|
Names[RTLIB::RINT_F64] = "rint";
|
|
|
|
Names[RTLIB::RINT_F80] = "rintl";
|
|
|
|
Names[RTLIB::RINT_PPCF128] = "rintl";
|
|
|
|
Names[RTLIB::NEARBYINT_F32] = "nearbyintf";
|
|
|
|
Names[RTLIB::NEARBYINT_F64] = "nearbyint";
|
|
|
|
Names[RTLIB::NEARBYINT_F80] = "nearbyintl";
|
|
|
|
Names[RTLIB::NEARBYINT_PPCF128] = "nearbyintl";
|
|
|
|
Names[RTLIB::FLOOR_F32] = "floorf";
|
|
|
|
Names[RTLIB::FLOOR_F64] = "floor";
|
|
|
|
Names[RTLIB::FLOOR_F80] = "floorl";
|
|
|
|
Names[RTLIB::FLOOR_PPCF128] = "floorl";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2";
|
|
|
|
Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2";
|
2008-08-07 19:01:24 +00:00
|
|
|
Names[RTLIB::FPROUND_F80_F32] = "__truncxfsf2";
|
|
|
|
Names[RTLIB::FPROUND_PPCF128_F32] = "__trunctfsf2";
|
|
|
|
Names[RTLIB::FPROUND_F80_F64] = "__truncxfdf2";
|
|
|
|
Names[RTLIB::FPROUND_PPCF128_F64] = "__trunctfdf2";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F64_I32] = "__fixdfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F64_I64] = "__fixdfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F64_I128] = "__fixdfti";
|
2008-07-10 15:33:02 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I32] = "__fixxfsi";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I64] = "__fixxfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I128] = "__fixxfti";
|
2008-06-25 20:24:48 +00:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F32_I128] = "__fixunssfti";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F64_I32] = "__fixunsdfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F64_I64] = "__fixunsdfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F64_I128] = "__fixunsdfti";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F80_I32] = "__fixunsxfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F80_I64] = "__fixunsxfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOUINT_F80_I128] = "__fixunsxfti";
|
2008-06-25 20:24:48 +00:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I32] = "__fixunstfsi";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I64] = "__fixunstfdi";
|
2008-03-10 23:03:31 +00:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I128] = "__fixunstfti";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf";
|
2008-07-11 16:57:02 +00:00
|
|
|
Names[RTLIB::SINTTOFP_I32_F80] = "__floatsixf";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_PPCF128] = "__floatsitf";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf";
|
2007-10-05 20:04:43 +00:00
|
|
|
Names[RTLIB::SINTTOFP_I64_F80] = "__floatdixf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_PPCF128] = "__floatditf";
|
2008-03-05 01:08:17 +00:00
|
|
|
Names[RTLIB::SINTTOFP_I128_F32] = "__floattisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I128_F64] = "__floattidf";
|
|
|
|
Names[RTLIB::SINTTOFP_I128_F80] = "__floattixf";
|
|
|
|
Names[RTLIB::SINTTOFP_I128_PPCF128] = "__floattitf";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf";
|
2008-07-11 17:00:14 +00:00
|
|
|
Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf";
|
2008-07-11 17:00:14 +00:00
|
|
|
Names[RTLIB::UINTTOFP_I64_F80] = "__floatundixf";
|
|
|
|
Names[RTLIB::UINTTOFP_I64_PPCF128] = "__floatunditf";
|
|
|
|
Names[RTLIB::UINTTOFP_I128_F32] = "__floatuntisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I128_F64] = "__floatuntidf";
|
|
|
|
Names[RTLIB::UINTTOFP_I128_F80] = "__floatuntixf";
|
|
|
|
Names[RTLIB::UINTTOFP_I128_PPCF128] = "__floatuntitf";
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::OEQ_F32] = "__eqsf2";
|
|
|
|
Names[RTLIB::OEQ_F64] = "__eqdf2";
|
|
|
|
Names[RTLIB::UNE_F32] = "__nesf2";
|
|
|
|
Names[RTLIB::UNE_F64] = "__nedf2";
|
|
|
|
Names[RTLIB::OGE_F32] = "__gesf2";
|
|
|
|
Names[RTLIB::OGE_F64] = "__gedf2";
|
|
|
|
Names[RTLIB::OLT_F32] = "__ltsf2";
|
|
|
|
Names[RTLIB::OLT_F64] = "__ltdf2";
|
|
|
|
Names[RTLIB::OLE_F32] = "__lesf2";
|
|
|
|
Names[RTLIB::OLE_F64] = "__ledf2";
|
|
|
|
Names[RTLIB::OGT_F32] = "__gtsf2";
|
|
|
|
Names[RTLIB::OGT_F64] = "__gtdf2";
|
|
|
|
Names[RTLIB::UO_F32] = "__unordsf2";
|
|
|
|
Names[RTLIB::UO_F64] = "__unorddf2";
|
2007-01-31 09:29:11 +00:00
|
|
|
Names[RTLIB::O_F32] = "__unordsf2";
|
|
|
|
Names[RTLIB::O_F64] = "__unorddf2";
|
|
|
|
}
|
|
|
|
|
2008-07-17 02:36:29 +00:00
|
|
|
/// getFPEXT - Return the FPEXT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getFPEXT(MVT OpVT, MVT RetVT) {
|
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::f64)
|
|
|
|
return FPEXT_F32_F64;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPROUND - Return the FPROUND_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getFPROUND(MVT OpVT, MVT RetVT) {
|
2008-08-07 19:01:24 +00:00
|
|
|
if (RetVT == MVT::f32) {
|
|
|
|
if (OpVT == MVT::f64)
|
2008-07-17 02:36:29 +00:00
|
|
|
return FPROUND_F64_F32;
|
2008-08-07 19:01:24 +00:00
|
|
|
if (OpVT == MVT::f80)
|
|
|
|
return FPROUND_F80_F32;
|
|
|
|
if (OpVT == MVT::ppcf128)
|
|
|
|
return FPROUND_PPCF128_F32;
|
|
|
|
} else if (RetVT == MVT::f64) {
|
|
|
|
if (OpVT == MVT::f80)
|
|
|
|
return FPROUND_F80_F64;
|
|
|
|
if (OpVT == MVT::ppcf128)
|
|
|
|
return FPROUND_PPCF128_F64;
|
2008-07-17 02:36:29 +00:00
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getFPTOSINT(MVT OpVT, MVT RetVT) {
|
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOSINT_F32_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOSINT_F32_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOSINT_F32_I128;
|
|
|
|
} else if (OpVT == MVT::f64) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOSINT_F64_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOSINT_F64_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOSINT_F64_I128;
|
|
|
|
} else if (OpVT == MVT::f80) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOSINT_F80_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOSINT_F80_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOSINT_F80_I128;
|
|
|
|
} else if (OpVT == MVT::ppcf128) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOSINT_PPCF128_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOSINT_PPCF128_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOSINT_PPCF128_I128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getFPTOUINT(MVT OpVT, MVT RetVT) {
|
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOUINT_F32_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOUINT_F32_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOUINT_F32_I128;
|
|
|
|
} else if (OpVT == MVT::f64) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOUINT_F64_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOUINT_F64_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOUINT_F64_I128;
|
|
|
|
} else if (OpVT == MVT::f80) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOUINT_F80_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOUINT_F80_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOUINT_F80_I128;
|
|
|
|
} else if (OpVT == MVT::ppcf128) {
|
|
|
|
if (RetVT == MVT::i32)
|
|
|
|
return FPTOUINT_PPCF128_I32;
|
|
|
|
if (RetVT == MVT::i64)
|
|
|
|
return FPTOUINT_PPCF128_I64;
|
|
|
|
if (RetVT == MVT::i128)
|
|
|
|
return FPTOUINT_PPCF128_I128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getSINTTOFP(MVT OpVT, MVT RetVT) {
|
|
|
|
if (OpVT == MVT::i32) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return SINTTOFP_I32_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return SINTTOFP_I32_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return SINTTOFP_I32_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return SINTTOFP_I32_PPCF128;
|
|
|
|
} else if (OpVT == MVT::i64) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return SINTTOFP_I64_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return SINTTOFP_I64_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return SINTTOFP_I64_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return SINTTOFP_I64_PPCF128;
|
|
|
|
} else if (OpVT == MVT::i128) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return SINTTOFP_I128_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return SINTTOFP_I128_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return SINTTOFP_I128_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return SINTTOFP_I128_PPCF128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
|
|
|
RTLIB::Libcall RTLIB::getUINTTOFP(MVT OpVT, MVT RetVT) {
|
|
|
|
if (OpVT == MVT::i32) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return UINTTOFP_I32_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return UINTTOFP_I32_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return UINTTOFP_I32_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return UINTTOFP_I32_PPCF128;
|
|
|
|
} else if (OpVT == MVT::i64) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return UINTTOFP_I64_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return UINTTOFP_I64_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return UINTTOFP_I64_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return UINTTOFP_I64_PPCF128;
|
|
|
|
} else if (OpVT == MVT::i128) {
|
|
|
|
if (RetVT == MVT::f32)
|
|
|
|
return UINTTOFP_I128_F32;
|
|
|
|
else if (RetVT == MVT::f64)
|
|
|
|
return UINTTOFP_I128_F64;
|
|
|
|
else if (RetVT == MVT::f80)
|
|
|
|
return UINTTOFP_I128_F80;
|
|
|
|
else if (RetVT == MVT::ppcf128)
|
|
|
|
return UINTTOFP_I128_PPCF128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
2007-01-31 09:29:11 +00:00
|
|
|
/// InitCmpLibcallCCs - Set default comparison libcall CC.
|
|
|
|
///
|
|
|
|
static void InitCmpLibcallCCs(ISD::CondCode *CCs) {
|
|
|
|
memset(CCs, ISD::SETCC_INVALID, sizeof(ISD::CondCode)*RTLIB::UNKNOWN_LIBCALL);
|
|
|
|
CCs[RTLIB::OEQ_F32] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::OEQ_F64] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::UNE_F32] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::UNE_F64] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::OGE_F32] = ISD::SETGE;
|
|
|
|
CCs[RTLIB::OGE_F64] = ISD::SETGE;
|
|
|
|
CCs[RTLIB::OLT_F32] = ISD::SETLT;
|
|
|
|
CCs[RTLIB::OLT_F64] = ISD::SETLT;
|
|
|
|
CCs[RTLIB::OLE_F32] = ISD::SETLE;
|
|
|
|
CCs[RTLIB::OLE_F64] = ISD::SETLE;
|
|
|
|
CCs[RTLIB::OGT_F32] = ISD::SETGT;
|
|
|
|
CCs[RTLIB::OGT_F64] = ISD::SETGT;
|
|
|
|
CCs[RTLIB::UO_F32] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::UO_F64] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::O_F32] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::O_F64] = ISD::SETEQ;
|
2007-01-12 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
TargetLowering::TargetLowering(TargetMachine &tm)
|
2006-01-29 08:41:12 +00:00
|
|
|
: TM(tm), TD(TM.getTargetData()) {
|
2008-05-05 19:05:59 +00:00
|
|
|
assert(ISD::BUILTIN_OP_END <= OpActionsCapacity &&
|
2005-01-07 07:44:53 +00:00
|
|
|
"Fixed size array in TargetLowering is not large enough!");
|
2005-01-16 07:28:11 +00:00
|
|
|
// All operations default to being supported.
|
|
|
|
memset(OpActions, 0, sizeof(OpActions));
|
2008-10-14 21:26:46 +00:00
|
|
|
memset(LoadExtActions, 0, sizeof(LoadExtActions));
|
2008-01-17 19:59:44 +00:00
|
|
|
memset(TruncStoreActions, 0, sizeof(TruncStoreActions));
|
2008-01-18 19:36:20 +00:00
|
|
|
memset(IndexedModeActions, 0, sizeof(IndexedModeActions));
|
|
|
|
memset(ConvertActions, 0, sizeof(ConvertActions));
|
2008-10-15 02:05:31 +00:00
|
|
|
memset(CondCodeActions, 0, sizeof(CondCodeActions));
|
2007-07-09 20:49:44 +00:00
|
|
|
|
2007-12-22 20:47:56 +00:00
|
|
|
// Set default actions for various operations.
|
2006-11-09 18:56:43 +00:00
|
|
|
for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) {
|
2007-12-22 20:47:56 +00:00
|
|
|
// Default all indexed load / store to expand.
|
2006-11-09 18:56:43 +00:00
|
|
|
for (unsigned IM = (unsigned)ISD::PRE_INC;
|
|
|
|
IM != (unsigned)ISD::LAST_INDEXED_MODE; ++IM) {
|
2008-06-06 12:08:01 +00:00
|
|
|
setIndexedLoadAction(IM, (MVT::SimpleValueType)VT, Expand);
|
|
|
|
setIndexedStoreAction(IM, (MVT::SimpleValueType)VT, Expand);
|
2006-11-09 18:56:43 +00:00
|
|
|
}
|
2007-12-22 20:47:56 +00:00
|
|
|
|
|
|
|
// These operations default to expand.
|
2008-06-06 12:08:01 +00:00
|
|
|
setOperationAction(ISD::FGETSIGN, (MVT::SimpleValueType)VT, Expand);
|
2006-11-09 18:56:43 +00:00
|
|
|
}
|
2008-03-10 19:38:10 +00:00
|
|
|
|
|
|
|
// Most targets ignore the @llvm.prefetch intrinsic.
|
|
|
|
setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
|
2008-02-14 08:57:00 +00:00
|
|
|
|
|
|
|
// ConstantFP nodes default to expand. Targets can either change this to
|
|
|
|
// Legal, in which case all fp constants are legal, or use addLegalFPImmediate
|
|
|
|
// to optimize expansions for certain constants.
|
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f80, Expand);
|
2005-01-07 07:44:53 +00:00
|
|
|
|
2008-09-22 21:57:32 +00:00
|
|
|
// These library functions default to expand.
|
|
|
|
setOperationAction(ISD::FLOG , MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FLOG2, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FLOG10,MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FEXP , MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FEXP2, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FLOG , MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FLOG2, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FLOG10,MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FEXP , MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FEXP2, MVT::f32, Expand);
|
|
|
|
|
2008-01-15 21:58:08 +00:00
|
|
|
// Default ISD::TRAP to expand (which turns it into abort).
|
|
|
|
setOperationAction(ISD::TRAP, MVT::Other, Expand);
|
|
|
|
|
2006-05-03 01:29:57 +00:00
|
|
|
IsLittleEndian = TD->isLittleEndian();
|
2006-10-06 22:52:08 +00:00
|
|
|
UsesGlobalOffsetTable = false;
|
2008-03-10 15:42:14 +00:00
|
|
|
ShiftAmountTy = PointerTy = getValueType(TD->getIntPtrType());
|
2005-01-19 03:36:14 +00:00
|
|
|
ShiftAmtHandling = Undefined;
|
2005-01-07 07:44:53 +00:00
|
|
|
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
|
2007-09-07 04:06:50 +00:00
|
|
|
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
|
2006-02-14 08:38:30 +00:00
|
|
|
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
|
2005-08-27 19:09:02 +00:00
|
|
|
allowUnalignedMemoryAccesses = false;
|
2006-12-10 23:12:42 +00:00
|
|
|
UseUnderscoreSetJmp = false;
|
|
|
|
UseUnderscoreLongJmp = false;
|
2007-02-25 01:28:05 +00:00
|
|
|
SelectIsExpensive = false;
|
2005-10-21 00:02:42 +00:00
|
|
|
IntDivIsCheap = false;
|
|
|
|
Pow2DivIsCheap = false;
|
2006-01-25 18:57:15 +00:00
|
|
|
StackPointerRegisterToSaveRestore = 0;
|
2007-02-22 18:04:49 +00:00
|
|
|
ExceptionPointerRegister = 0;
|
|
|
|
ExceptionSelectorRegister = 0;
|
2008-11-23 15:47:28 +00:00
|
|
|
BooleanContents = UndefinedBooleanContent;
|
2006-01-25 18:52:42 +00:00
|
|
|
SchedPreferenceInfo = SchedulingForLatency;
|
2006-09-05 17:39:15 +00:00
|
|
|
JumpBufSize = 0;
|
2006-09-04 07:44:11 +00:00
|
|
|
JumpBufAlignment = 0;
|
2007-05-16 23:45:53 +00:00
|
|
|
IfCvtBlockSizeLimit = 2;
|
2008-02-28 00:43:03 +00:00
|
|
|
IfCvtDupBlockSizeLimit = 0;
|
|
|
|
PrefLoopAlignment = 0;
|
2007-01-12 02:11:51 +00:00
|
|
|
|
|
|
|
InitLibcallNames(LibcallRoutineNames);
|
2007-01-31 09:29:11 +00:00
|
|
|
InitCmpLibcallCCs(CmpLibcallCCs);
|
2007-09-25 15:10:49 +00:00
|
|
|
|
|
|
|
// Tell Legalize whether the assembler supports DEBUG_LOC.
|
2008-10-13 12:41:46 +00:00
|
|
|
const TargetAsmInfo *TASM = TM.getTargetAsmInfo();
|
|
|
|
if (!TASM || !TASM->hasDotLocAndDotFile())
|
2007-09-25 15:10:49 +00:00
|
|
|
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
|
2005-01-07 07:44:53 +00:00
|
|
|
}
|
|
|
|
|
2005-01-16 07:28:11 +00:00
|
|
|
TargetLowering::~TargetLowering() {}
|
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
/// computeRegisterProperties - Once all of the register classes are added,
|
|
|
|
/// this allows us to compute derived properties we expose.
|
|
|
|
void TargetLowering::computeRegisterProperties() {
|
2005-11-29 05:45:29 +00:00
|
|
|
assert(MVT::LAST_VALUETYPE <= 32 &&
|
2005-01-16 01:10:58 +00:00
|
|
|
"Too many value types for ValueTypeActions to hold!");
|
|
|
|
|
2007-06-28 23:29:44 +00:00
|
|
|
// Everything defaults to needing one register.
|
|
|
|
for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) {
|
2007-06-21 14:42:22 +00:00
|
|
|
NumRegistersForVT[i] = 1;
|
2008-06-06 12:08:01 +00:00
|
|
|
RegisterTypeForVT[i] = TransformToType[i] = (MVT::SimpleValueType)i;
|
2007-06-28 23:29:44 +00:00
|
|
|
}
|
|
|
|
// ...except isVoid, which doesn't need any registers.
|
|
|
|
NumRegistersForVT[MVT::isVoid] = 0;
|
2005-04-21 22:55:34 +00:00
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
// Find the largest integer register class.
|
2008-06-09 15:48:25 +00:00
|
|
|
unsigned LargestIntReg = MVT::LAST_INTEGER_VALUETYPE;
|
2005-01-07 07:44:53 +00:00
|
|
|
for (; RegClassForVT[LargestIntReg] == 0; --LargestIntReg)
|
|
|
|
assert(LargestIntReg != MVT::i1 && "No integer registers defined!");
|
|
|
|
|
|
|
|
// Every integer value type larger than this largest register takes twice as
|
|
|
|
// many registers to represent as the previous ValueType.
|
2008-06-06 12:08:01 +00:00
|
|
|
for (unsigned ExpandedReg = LargestIntReg + 1; ; ++ExpandedReg) {
|
|
|
|
MVT EVT = (MVT::SimpleValueType)ExpandedReg;
|
|
|
|
if (!EVT.isInteger())
|
|
|
|
break;
|
2007-06-21 14:42:22 +00:00
|
|
|
NumRegistersForVT[ExpandedReg] = 2*NumRegistersForVT[ExpandedReg-1];
|
2008-06-06 12:08:01 +00:00
|
|
|
RegisterTypeForVT[ExpandedReg] = (MVT::SimpleValueType)LargestIntReg;
|
|
|
|
TransformToType[ExpandedReg] = (MVT::SimpleValueType)(ExpandedReg - 1);
|
|
|
|
ValueTypeActions.setTypeAction(EVT, Expand);
|
2007-06-28 23:29:44 +00:00
|
|
|
}
|
2005-01-07 07:44:53 +00:00
|
|
|
|
2007-06-28 23:29:44 +00:00
|
|
|
// Inspect all of the ValueType's smaller than the largest integer
|
|
|
|
// register to see which ones need promotion.
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned LegalIntReg = LargestIntReg;
|
|
|
|
for (unsigned IntReg = LargestIntReg - 1;
|
|
|
|
IntReg >= (unsigned)MVT::i1; --IntReg) {
|
|
|
|
MVT IVT = (MVT::SimpleValueType)IntReg;
|
|
|
|
if (isTypeLegal(IVT)) {
|
2007-06-28 23:29:44 +00:00
|
|
|
LegalIntReg = IntReg;
|
|
|
|
} else {
|
2008-06-06 12:08:01 +00:00
|
|
|
RegisterTypeForVT[IntReg] = TransformToType[IntReg] =
|
|
|
|
(MVT::SimpleValueType)LegalIntReg;
|
|
|
|
ValueTypeActions.setTypeAction(IVT, Promote);
|
2007-06-28 23:29:44 +00:00
|
|
|
}
|
|
|
|
}
|
2005-04-21 22:55:34 +00:00
|
|
|
|
2007-10-05 20:04:43 +00:00
|
|
|
// ppcf128 type is really two f64's.
|
|
|
|
if (!isTypeLegal(MVT::ppcf128)) {
|
|
|
|
NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64];
|
|
|
|
RegisterTypeForVT[MVT::ppcf128] = MVT::f64;
|
|
|
|
TransformToType[MVT::ppcf128] = MVT::f64;
|
|
|
|
ValueTypeActions.setTypeAction(MVT::ppcf128, Expand);
|
|
|
|
}
|
|
|
|
|
2007-06-28 23:29:44 +00:00
|
|
|
// Decide how to handle f64. If the target does not have native f64 support,
|
|
|
|
// expand it to i64 and we will be generating soft float library calls.
|
|
|
|
if (!isTypeLegal(MVT::f64)) {
|
2007-06-21 14:42:22 +00:00
|
|
|
NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64];
|
2007-06-28 23:29:44 +00:00
|
|
|
RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64];
|
|
|
|
TransformToType[MVT::f64] = MVT::i64;
|
|
|
|
ValueTypeActions.setTypeAction(MVT::f64, Expand);
|
2006-12-09 02:42:38 +00:00
|
|
|
}
|
2007-06-28 23:29:44 +00:00
|
|
|
|
|
|
|
// Decide how to handle f32. If the target does not have native support for
|
|
|
|
// f32, promote it to f64 if it is legal. Otherwise, expand it to i32.
|
|
|
|
if (!isTypeLegal(MVT::f32)) {
|
|
|
|
if (isTypeLegal(MVT::f64)) {
|
|
|
|
NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::f64];
|
|
|
|
RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::f64];
|
|
|
|
TransformToType[MVT::f32] = MVT::f64;
|
|
|
|
ValueTypeActions.setTypeAction(MVT::f32, Promote);
|
|
|
|
} else {
|
|
|
|
NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32];
|
|
|
|
RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::i32];
|
|
|
|
TransformToType[MVT::f32] = MVT::i32;
|
|
|
|
ValueTypeActions.setTypeAction(MVT::f32, Expand);
|
|
|
|
}
|
2006-12-09 02:42:38 +00:00
|
|
|
}
|
2005-11-22 01:29:36 +00:00
|
|
|
|
2007-06-28 23:29:44 +00:00
|
|
|
// Loop over all of the vector value types to see which need transformations.
|
2008-06-06 12:08:01 +00:00
|
|
|
for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE;
|
|
|
|
i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
|
|
|
|
MVT VT = (MVT::SimpleValueType)i;
|
|
|
|
if (!isTypeLegal(VT)) {
|
|
|
|
MVT IntermediateVT, RegisterVT;
|
2007-06-28 23:29:44 +00:00
|
|
|
unsigned NumIntermediates;
|
|
|
|
NumRegistersForVT[i] =
|
2008-06-06 12:08:01 +00:00
|
|
|
getVectorTypeBreakdown(VT,
|
2007-06-28 23:29:44 +00:00
|
|
|
IntermediateVT, NumIntermediates,
|
|
|
|
RegisterVT);
|
|
|
|
RegisterTypeForVT[i] = RegisterVT;
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
// Determine if there is a legal wider type.
|
|
|
|
bool IsLegalWiderType = false;
|
|
|
|
MVT EltVT = VT.getVectorElementType();
|
|
|
|
unsigned NElts = VT.getVectorNumElements();
|
|
|
|
for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) {
|
|
|
|
MVT SVT = (MVT::SimpleValueType)nVT;
|
|
|
|
if (isTypeLegal(SVT) && SVT.getVectorElementType() == EltVT &&
|
|
|
|
SVT.getVectorNumElements() > NElts) {
|
|
|
|
TransformToType[i] = SVT;
|
|
|
|
ValueTypeActions.setTypeAction(VT, Promote);
|
|
|
|
IsLegalWiderType = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!IsLegalWiderType) {
|
|
|
|
MVT NVT = VT.getPow2VectorType();
|
|
|
|
if (NVT == VT) {
|
|
|
|
// Type is already a power of 2. The default action is to split.
|
|
|
|
TransformToType[i] = MVT::Other;
|
|
|
|
ValueTypeActions.setTypeAction(VT, Expand);
|
|
|
|
} else {
|
|
|
|
TransformToType[i] = NVT;
|
|
|
|
ValueTypeActions.setTypeAction(VT, Promote);
|
|
|
|
}
|
|
|
|
}
|
2007-06-25 16:23:39 +00:00
|
|
|
}
|
2006-03-16 19:50:01 +00:00
|
|
|
}
|
2005-01-16 01:10:58 +00:00
|
|
|
}
|
2005-01-16 07:28:11 +00:00
|
|
|
|
2005-12-20 06:22:03 +00:00
|
|
|
const char *TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-12-21 23:05:39 +00:00
|
|
|
|
2008-03-10 15:42:14 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
MVT TargetLowering::getSetCCResultType(const SDValue &) const {
|
2008-03-10 15:42:14 +00:00
|
|
|
return getValueType(TD->getIntPtrType());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-25 16:23:39 +00:00
|
|
|
/// getVectorTypeBreakdown - Vector types are broken down into some number of
|
|
|
|
/// legal first class types. For example, MVT::v8f32 maps to 2 MVT::v4f32
|
2006-03-31 00:28:56 +00:00
|
|
|
/// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack.
|
2007-06-25 16:23:39 +00:00
|
|
|
/// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86.
|
2006-03-31 00:28:56 +00:00
|
|
|
///
|
2007-06-25 16:23:39 +00:00
|
|
|
/// This method returns the number of registers needed, and the VT for each
|
2007-06-28 23:29:44 +00:00
|
|
|
/// register. It also returns the VT and quantity of the intermediate values
|
|
|
|
/// before they are promoted/expanded.
|
2006-03-31 00:28:56 +00:00
|
|
|
///
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned TargetLowering::getVectorTypeBreakdown(MVT VT,
|
|
|
|
MVT &IntermediateVT,
|
2007-06-28 23:29:44 +00:00
|
|
|
unsigned &NumIntermediates,
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT &RegisterVT) const {
|
2006-03-31 00:28:56 +00:00
|
|
|
// Figure out the right, legal destination reg to copy into.
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
MVT EltTy = VT.getVectorElementType();
|
2006-03-31 00:28:56 +00:00
|
|
|
|
|
|
|
unsigned NumVectorRegs = 1;
|
|
|
|
|
2007-11-27 19:28:48 +00:00
|
|
|
// FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we
|
|
|
|
// could break down into LHS/RHS like LegalizeDAG does.
|
|
|
|
if (!isPowerOf2_32(NumElts)) {
|
|
|
|
NumVectorRegs = NumElts;
|
|
|
|
NumElts = 1;
|
|
|
|
}
|
|
|
|
|
2006-03-31 00:28:56 +00:00
|
|
|
// Divide the input until we get to a supported size. This will always
|
|
|
|
// end with a scalar if the target doesn't support vectors.
|
2008-06-06 12:08:01 +00:00
|
|
|
while (NumElts > 1 && !isTypeLegal(MVT::getVectorVT(EltTy, NumElts))) {
|
2006-03-31 00:28:56 +00:00
|
|
|
NumElts >>= 1;
|
|
|
|
NumVectorRegs <<= 1;
|
|
|
|
}
|
2007-06-28 23:29:44 +00:00
|
|
|
|
|
|
|
NumIntermediates = NumVectorRegs;
|
2006-03-31 00:28:56 +00:00
|
|
|
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT NewVT = MVT::getVectorVT(EltTy, NumElts);
|
2007-06-25 16:23:39 +00:00
|
|
|
if (!isTypeLegal(NewVT))
|
|
|
|
NewVT = EltTy;
|
2007-06-28 23:29:44 +00:00
|
|
|
IntermediateVT = NewVT;
|
2006-03-31 00:28:56 +00:00
|
|
|
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT DestVT = getTypeToTransformTo(NewVT);
|
2007-06-28 23:29:44 +00:00
|
|
|
RegisterVT = DestVT;
|
2008-06-08 20:54:56 +00:00
|
|
|
if (DestVT.bitsLT(NewVT)) {
|
2006-03-31 00:28:56 +00:00
|
|
|
// Value is expanded, e.g. i64 -> i16.
|
2008-06-06 12:08:01 +00:00
|
|
|
return NumVectorRegs*(NewVT.getSizeInBits()/DestVT.getSizeInBits());
|
2006-03-31 00:28:56 +00:00
|
|
|
} else {
|
|
|
|
// Otherwise, promotion or legal types use the same number of registers as
|
|
|
|
// the vector decimated to the appropriate level.
|
2006-03-31 00:46:36 +00:00
|
|
|
return NumVectorRegs;
|
2006-03-31 00:28:56 +00:00
|
|
|
}
|
|
|
|
|
2006-05-17 18:10:06 +00:00
|
|
|
return 1;
|
2006-03-31 00:28:56 +00:00
|
|
|
}
|
|
|
|
|
2008-10-30 08:01:45 +00:00
|
|
|
/// getWidenVectorType: given a vector type, returns the type to widen to
|
|
|
|
/// (e.g., v7i8 to v8i8). If the vector type is legal, it returns itself.
|
|
|
|
/// If there is no vector type that we want to widen to, returns MVT::Other
|
2008-11-06 05:31:54 +00:00
|
|
|
/// When and where to widen is target dependent based on the cost of
|
2008-10-30 08:01:45 +00:00
|
|
|
/// scalarizing vs using the wider vector type.
|
|
|
|
MVT TargetLowering::getWidenVectorType(MVT VT) {
|
|
|
|
assert(VT.isVector());
|
|
|
|
if (isTypeLegal(VT))
|
|
|
|
return VT;
|
|
|
|
|
|
|
|
// Default is not to widen until moved to LegalizeTypes
|
|
|
|
return MVT::Other;
|
|
|
|
}
|
|
|
|
|
2008-01-24 00:22:01 +00:00
|
|
|
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
|
2008-02-28 22:31:51 +00:00
|
|
|
/// function arguments in the caller parameter area. This is the actual
|
|
|
|
/// alignment, not its logarithm.
|
2008-01-24 00:22:01 +00:00
|
|
|
unsigned TargetLowering::getByValTypeAlignment(const Type *Ty) const {
|
2008-02-28 22:31:51 +00:00
|
|
|
return TD->getCallFrameTypeAlignment(Ty);
|
2008-01-24 00:22:01 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table,
|
|
|
|
SelectionDAG &DAG) const {
|
Much improved pic jumptable codegen:
Then:
call "L1$pb"
"L1$pb":
popl %eax
...
LBB1_1: # entry
imull $4, %ecx, %ecx
leal LJTI1_0-"L1$pb"(%eax), %edx
addl LJTI1_0-"L1$pb"(%ecx,%eax), %edx
jmpl *%edx
.align 2
.set L1_0_set_3,LBB1_3-LJTI1_0
.set L1_0_set_2,LBB1_2-LJTI1_0
.set L1_0_set_5,LBB1_5-LJTI1_0
.set L1_0_set_4,LBB1_4-LJTI1_0
LJTI1_0:
.long L1_0_set_3
.long L1_0_set_2
Now:
call "L1$pb"
"L1$pb":
popl %eax
...
LBB1_1: # entry
addl LJTI1_0-"L1$pb"(%eax,%ecx,4), %eax
jmpl *%eax
.align 2
.set L1_0_set_3,LBB1_3-"L1$pb"
.set L1_0_set_2,LBB1_2-"L1$pb"
.set L1_0_set_5,LBB1_5-"L1$pb"
.set L1_0_set_4,LBB1_4-"L1$pb"
LJTI1_0:
.long L1_0_set_3
.long L1_0_set_2
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43924 91177308-0d34-0410-b5e6-96231b3b80d8
2007-11-09 01:32:10 +00:00
|
|
|
if (usesGlobalOffsetTable())
|
|
|
|
return DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, getPointerTy());
|
|
|
|
return Table;
|
|
|
|
}
|
|
|
|
|
Teach DAGCombine to fold constant offsets into GlobalAddress nodes,
and add a TargetLowering hook for it to use to determine when this
is legal (i.e. not in PIC mode, etc.)
This allows instruction selection to emit folded constant offsets
in more cases, such as the included testcase, eliminating the need
for explicit arithmetic instructions.
This eliminates the need for the C++ code in X86ISelDAGToDAG.cpp
that attempted to achieve the same effect, but wasn't as effective.
Also, fix handling of offsets in GlobalAddressSDNodes in several
places, including changing GlobalAddressSDNode's offset from
int to int64_t.
The Mips, Alpha, Sparc, and CellSPU targets appear to be
unaware of GlobalAddress offsets currently, so set the hook to
false on those targets.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57748 91177308-0d34-0410-b5e6-96231b3b80d8
2008-10-18 02:06:02 +00:00
|
|
|
bool
|
|
|
|
TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
|
|
|
// Assume that everything is safe in static mode.
|
|
|
|
if (getTargetMachine().getRelocationModel() == Reloc::Static)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// In dynamic-no-pic mode, assume that known defined values are safe.
|
|
|
|
if (getTargetMachine().getRelocationModel() == Reloc::DynamicNoPIC &&
|
|
|
|
GA &&
|
|
|
|
!GA->getGlobal()->isDeclaration() &&
|
|
|
|
!GA->getGlobal()->mayBeOverridden())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Otherwise assume nothing is safe.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-02-04 02:13:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Optimization Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
/// ShrinkDemandedConstant - Check to see if the specified operand of the
|
|
|
|
/// specified instruction is a constant integer. If so, check to see if there
|
|
|
|
/// are any bits set in the constant that are not demanded. If so, shrink the
|
|
|
|
/// constant and return true.
|
2008-07-27 21:46:04 +00:00
|
|
|
bool TargetLowering::TargetLoweringOpt::ShrinkDemandedConstant(SDValue Op,
|
2008-02-27 00:25:32 +00:00
|
|
|
const APInt &Demanded) {
|
2006-02-26 23:36:02 +00:00
|
|
|
// FIXME: ISD::SELECT, ISD::SELECT_CC
|
2006-02-16 21:11:51 +00:00
|
|
|
switch(Op.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR:
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
|
2008-02-27 00:25:32 +00:00
|
|
|
if (C->getAPIntValue().intersects(~Demanded)) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue New = DAG.getNode(Op.getOpcode(), VT, Op.getOperand(0),
|
2008-02-27 00:25:32 +00:00
|
|
|
DAG.getConstant(Demanded &
|
|
|
|
C->getAPIntValue(),
|
2006-02-16 21:11:51 +00:00
|
|
|
VT));
|
|
|
|
return CombineTo(Op, New);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// SimplifyDemandedBits - Look at Op. At this point, we know that only the
|
|
|
|
/// DemandedMask bits of the result of Op are ever used downstream. If we can
|
|
|
|
/// use this information to simplify Op, create a new simplified DAG node and
|
|
|
|
/// return true, returning the original and new nodes in Old and New. Otherwise,
|
|
|
|
/// analyze the expression and return a mask of KnownOne and KnownZero bits for
|
|
|
|
/// the expression (used to simplify the caller). The KnownZero/One bits may
|
|
|
|
/// only be accurate for those bits in the DemandedMask.
|
2008-07-27 21:46:04 +00:00
|
|
|
bool TargetLowering::SimplifyDemandedBits(SDValue Op,
|
2008-02-27 00:25:32 +00:00
|
|
|
const APInt &DemandedMask,
|
|
|
|
APInt &KnownZero,
|
|
|
|
APInt &KnownOne,
|
2006-02-16 21:11:51 +00:00
|
|
|
TargetLoweringOpt &TLO,
|
|
|
|
unsigned Depth) const {
|
2008-02-27 00:25:32 +00:00
|
|
|
unsigned BitWidth = DemandedMask.getBitWidth();
|
|
|
|
assert(Op.getValueSizeInBits() == BitWidth &&
|
|
|
|
"Mask size mismatches value type size!");
|
|
|
|
APInt NewMask = DemandedMask;
|
|
|
|
|
|
|
|
// Don't know anything.
|
|
|
|
KnownZero = KnownOne = APInt(BitWidth, 0);
|
2007-05-17 18:19:23 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// Other users may use these bits.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (!Op.getNode()->hasOneUse()) {
|
2006-02-16 21:11:51 +00:00
|
|
|
if (Depth != 0) {
|
|
|
|
// If not at the root, Just compute the KnownZero/KnownOne bits to
|
|
|
|
// simplify things downstream.
|
2007-06-22 14:59:07 +00:00
|
|
|
TLO.DAG.ComputeMaskedBits(Op, DemandedMask, KnownZero, KnownOne, Depth);
|
2006-02-16 21:11:51 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// If this is the root being simplified, allow it to have multiple uses,
|
2008-02-27 00:25:32 +00:00
|
|
|
// just set the NewMask to all bits.
|
|
|
|
NewMask = APInt::getAllOnesValue(BitWidth);
|
2006-02-16 21:11:51 +00:00
|
|
|
} else if (DemandedMask == 0) {
|
|
|
|
// Not demanding any bits from Op.
|
|
|
|
if (Op.getOpcode() != ISD::UNDEF)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::UNDEF, Op.getValueType()));
|
2006-02-03 22:24:05 +00:00
|
|
|
return false;
|
2006-02-16 21:11:51 +00:00
|
|
|
} else if (Depth == 6) { // Limit search depth.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut;
|
2006-02-03 22:24:05 +00:00
|
|
|
switch (Op.getOpcode()) {
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::Constant:
|
|
|
|
// We know all of the bits for a constant!
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownOne = cast<ConstantSDNode>(Op)->getAPIntValue() & NewMask;
|
|
|
|
KnownZero = ~KnownOne & NewMask;
|
2006-02-26 23:36:02 +00:00
|
|
|
return false; // Don't fall through, will infinitely loop.
|
2006-02-03 22:24:05 +00:00
|
|
|
case ISD::AND:
|
2006-02-27 00:36:27 +00:00
|
|
|
// If the RHS is a constant, check to see if the LHS would be zero without
|
|
|
|
// using the bits from the RHS. Below, we use knowledge about the RHS to
|
|
|
|
// simplify the LHS, here we're using information from the LHS to simplify
|
|
|
|
// the RHS.
|
|
|
|
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt LHSZero, LHSOne;
|
|
|
|
TLO.DAG.ComputeMaskedBits(Op.getOperand(0), NewMask,
|
2007-06-22 14:59:07 +00:00
|
|
|
LHSZero, LHSOne, Depth+1);
|
2006-02-27 00:36:27 +00:00
|
|
|
// If the LHS already has zeros where RHSC does, this and is dead.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask))
|
2006-02-27 00:36:27 +00:00
|
|
|
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.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask))
|
2006-02-27 00:36:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), ~KnownZero & NewMask,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known one on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'and'.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If all of the demanded bits in the inputs are known zeros, return zero.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & (KnownZero|KnownZero2)) == NewMask)
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getConstant(0, Op.getValueType()));
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, ~KnownZero2 & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return true;
|
Just like we use the RHS of an AND to simplify the LHS, use the LHS to
simplify the RHS. This allows for the elimination of many thousands of
ands from multisource, and compiles CodeGen/PowerPC/and-elim.ll:test2
into this:
_test2:
srwi r2, r3, 1
xori r3, r2, 40961
blr
instead of this:
_test2:
rlwinm r2, r3, 31, 17, 31
xori r2, r2, 40961
rlwinm r3, r2, 0, 16, 31
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26388 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-27 00:22:28 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// Output known-1 bits are only known if set in both the LHS & RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
|
|
|
KnownZero |= KnownZero2;
|
|
|
|
break;
|
|
|
|
case ISD::OR:
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), ~KnownOne & NewMask,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'or'.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownOne2 & KnownZero) == (~KnownOne2 & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownOne & KnownZero2) == (~KnownOne & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If all of the potentially set bits on one side are known to be set on
|
|
|
|
// the other side, just use the 'other' side.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
// Output known-1 are known to be set if set in either the LHS | RHS.
|
|
|
|
KnownOne |= KnownOne2;
|
|
|
|
break;
|
|
|
|
case ISD::XOR:
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), NewMask, KnownZero2,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'xor'.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((KnownZero & NewMask) == NewMask)
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((KnownZero2 & NewMask) == NewMask)
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
2006-11-27 21:50:02 +00:00
|
|
|
|
|
|
|
// If all of the unknown bits are known to be zero on one side or the other
|
|
|
|
// (but not both) turn this into an *inclusive* or.
|
|
|
|
// e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & ~KnownZero & ~KnownZero2) == 0)
|
2006-11-27 21:50:02 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, Op.getValueType(),
|
|
|
|
Op.getOperand(0),
|
|
|
|
Op.getOperand(1)));
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
|
|
|
KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
|
|
|
|
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
|
|
|
KnownOneOut = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
|
|
|
|
|
|
|
|
// If all of the demanded bits on one side are known, and all of the set
|
|
|
|
// bits on that side are also known to be set on the other side, turn this
|
|
|
|
// into an AND, as we know the bits will be cleared.
|
|
|
|
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known
|
2006-02-16 21:11:51 +00:00
|
|
|
if ((KnownOne & KnownOne2) == KnownOne) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue ANDC = TLO.DAG.getConstant(~KnownOne & NewMask, VT);
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, VT, Op.getOperand(0),
|
|
|
|
ANDC));
|
|
|
|
}
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2008-04-06 21:23:02 +00:00
|
|
|
// for XOR, we prefer to force bits to 1 if they will make a -1.
|
|
|
|
// if we can't force bits, try to shrink constant
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
APInt Expanded = C->getAPIntValue() | (~NewMask);
|
|
|
|
// if we can expand it to have all bits set, do it
|
|
|
|
if (Expanded.isAllOnesValue()) {
|
|
|
|
if (Expanded != C->getAPIntValue()) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue New = TLO.DAG.getNode(Op.getOpcode(), VT, Op.getOperand(0),
|
2008-04-06 21:23:02 +00:00
|
|
|
TLO.DAG.getConstant(Expanded, VT));
|
|
|
|
return TLO.CombineTo(Op, New);
|
|
|
|
}
|
|
|
|
// if it already has all the bits set, nothing to change
|
|
|
|
// but don't shrink either!
|
|
|
|
} else if (TLO.ShrinkDemandedConstant(Op, NewMask)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
KnownOne = KnownOneOut;
|
|
|
|
break;
|
|
|
|
case ISD::SELECT:
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero2,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the operands are constants, see if we can simplify them.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-16 21:11:51 +00:00
|
|
|
return true;
|
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
break;
|
|
|
|
case ISD::SELECT_CC:
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(3), NewMask, KnownZero,
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero2,
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the operands are constants, see if we can simplify them.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-26 23:36:02 +00:00
|
|
|
return true;
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
2006-02-03 22:24:05 +00:00
|
|
|
break;
|
|
|
|
case ISD::SHL:
|
2006-02-16 21:11:51 +00:00
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue InOp = Op.getOperand(0);
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
// If the shift count is an invalid immediate, don't do anything.
|
|
|
|
if (ShAmt >= BitWidth)
|
|
|
|
break;
|
|
|
|
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
// If this is ((X >>u C1) << ShAmt), see if we can simplify this into a
|
|
|
|
// single shift. We can do this if the bottom bits (which are shifted
|
|
|
|
// out) are never demanded.
|
|
|
|
if (InOp.getOpcode() == ISD::SRL &&
|
|
|
|
isa<ConstantSDNode>(InOp.getOperand(1))) {
|
2008-02-27 00:25:32 +00:00
|
|
|
if (ShAmt && (NewMask & APInt::getLowBitsSet(BitWidth, ShAmt)) == 0) {
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned C1= cast<ConstantSDNode>(InOp.getOperand(1))->getZExtValue();
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
unsigned Opc = ISD::SHL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SRL;
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue NewSA =
|
2007-05-30 16:30:06 +00:00
|
|
|
TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2007-04-18 03:01:40 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, VT,
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), NewMask.lshr(ShAmt),
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-09-12 16:56:44 +00:00
|
|
|
KnownZero <<= SA->getZExtValue();
|
|
|
|
KnownOne <<= SA->getZExtValue();
|
2008-02-27 00:25:32 +00:00
|
|
|
// low bits known zero.
|
2008-09-12 16:56:44 +00:00
|
|
|
KnownZero |= APInt::getLowBitsSet(BitWidth, SA->getZExtValue());
|
2006-02-16 21:11:51 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRL:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned VTSize = VT.getSizeInBits();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue InOp = Op.getOperand(0);
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
// If the shift count is an invalid immediate, don't do anything.
|
|
|
|
if (ShAmt >= BitWidth)
|
|
|
|
break;
|
|
|
|
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
// If this is ((X << C1) >>u ShAmt), see if we can simplify this into a
|
|
|
|
// single shift. We can do this if the top bits (which are shifted out)
|
|
|
|
// are never demanded.
|
|
|
|
if (InOp.getOpcode() == ISD::SHL &&
|
|
|
|
isa<ConstantSDNode>(InOp.getOperand(1))) {
|
2008-02-27 00:25:32 +00:00
|
|
|
if (ShAmt && (NewMask & APInt::getHighBitsSet(VTSize, ShAmt)) == 0) {
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned C1= cast<ConstantSDNode>(InOp.getOperand(1))->getZExtValue();
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
unsigned Opc = ISD::SRL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SHL;
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue NewSA =
|
2007-04-17 22:53:02 +00:00
|
|
|
TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, VT,
|
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Compute the new bits that are at the top now.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(InOp, (NewMask << ShAmt),
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero = KnownZero.lshr(ShAmt);
|
|
|
|
KnownOne = KnownOne.lshr(ShAmt);
|
2006-06-13 16:52:37 +00:00
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero |= HighBits; // High bits known zero.
|
2006-02-16 21:11:51 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRA:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = Op.getValueType();
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
// If the shift count is an invalid immediate, don't do anything.
|
|
|
|
if (ShAmt >= BitWidth)
|
|
|
|
break;
|
|
|
|
|
|
|
|
APInt InDemandedMask = (NewMask << ShAmt);
|
2006-05-08 17:22:53 +00:00
|
|
|
|
|
|
|
// If any of the demanded bits are produced by the sign extension, we also
|
|
|
|
// demand the input sign bit.
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);
|
|
|
|
if (HighBits.intersects(NewMask))
|
2008-06-06 12:08:01 +00:00
|
|
|
InDemandedMask |= APInt::getSignBit(VT.getSizeInBits());
|
2006-05-08 17:22:53 +00:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero = KnownZero.lshr(ShAmt);
|
|
|
|
KnownOne = KnownOne.lshr(ShAmt);
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
// Handle the sign bit, adjusted to where it is now in the mask.
|
|
|
|
APInt SignBit = APInt::getSignBit(BitWidth).lshr(ShAmt);
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// If the input sign bit is known to be zero, or if none of the top bits
|
|
|
|
// are demanded, turn this into an unsigned shift right.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (KnownZero.intersects(SignBit) || (HighBits & ~NewMask) == HighBits) {
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, VT, Op.getOperand(0),
|
|
|
|
Op.getOperand(1)));
|
2008-02-27 00:25:32 +00:00
|
|
|
} else if (KnownOne.intersects(SignBit)) { // New bits are known one.
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne |= HighBits;
|
|
|
|
}
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Sign extension. Compute the demanded bits in the result that are not
|
2006-02-16 21:11:51 +00:00
|
|
|
// present in the input.
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt NewBits = APInt::getHighBitsSet(BitWidth,
|
2008-06-06 12:08:01 +00:00
|
|
|
BitWidth - EVT.getSizeInBits()) &
|
2008-02-27 00:25:32 +00:00
|
|
|
NewMask;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// If none of the extended bits are demanded, eliminate the sextinreg.
|
|
|
|
if (NewBits == 0)
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
|
2008-06-06 12:08:01 +00:00
|
|
|
APInt InSignBit = APInt::getSignBit(EVT.getSizeInBits());
|
2008-02-27 00:25:32 +00:00
|
|
|
InSignBit.zext(BitWidth);
|
|
|
|
APInt InputDemandedBits = APInt::getLowBitsSet(BitWidth,
|
2008-06-06 12:08:01 +00:00
|
|
|
EVT.getSizeInBits()) &
|
2008-02-27 00:25:32 +00:00
|
|
|
NewMask;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Since the sign extended bits are demanded, we know that the sign
|
2006-02-16 21:11:51 +00:00
|
|
|
// bit is demanded.
|
2006-02-26 23:36:02 +00:00
|
|
|
InputDemandedBits |= InSignBit;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
2006-02-03 22:24:05 +00:00
|
|
|
return true;
|
2006-02-16 21:11:51 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// If the input sign bit is known zero, convert this into a zero extension.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (KnownZero.intersects(InSignBit))
|
2006-02-26 23:36:02 +00:00
|
|
|
return TLO.CombineTo(Op,
|
|
|
|
TLO.DAG.getZeroExtendInReg(Op.getOperand(0), EVT));
|
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
if (KnownOne.intersects(InSignBit)) { // Input sign bit known set
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
2006-02-26 23:36:02 +00:00
|
|
|
} else { // Input sign bit unknown
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
case ISD::ZERO_EXTEND: {
|
2008-02-27 00:25:32 +00:00
|
|
|
unsigned OperandBitWidth = Op.getOperand(0).getValueSizeInBits();
|
|
|
|
APInt InMask = NewMask;
|
|
|
|
InMask.trunc(OperandBitWidth);
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt NewBits =
|
|
|
|
APInt::getHighBitsSet(BitWidth, BitWidth - OperandBitWidth) & NewMask;
|
|
|
|
if (!NewBits.intersects(NewMask))
|
2006-02-26 23:36:02 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ANY_EXTEND,
|
|
|
|
Op.getValueType(),
|
|
|
|
Op.getOperand(0)));
|
|
|
|
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InMask,
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero.zext(BitWidth);
|
|
|
|
KnownOne.zext(BitWidth);
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownZero |= NewBits;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::SIGN_EXTEND: {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT InVT = Op.getOperand(0).getValueType();
|
|
|
|
unsigned InBits = InVT.getSizeInBits();
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt InMask = APInt::getLowBitsSet(BitWidth, InBits);
|
2008-03-11 21:29:43 +00:00
|
|
|
APInt InSignBit = APInt::getBitsSet(BitWidth, InBits - 1, InBits);
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt NewBits = ~InMask & NewMask;
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
|
|
|
if (NewBits == 0)
|
2007-02-01 04:55:59 +00:00
|
|
|
return TLO.CombineTo(Op,TLO.DAG.getNode(ISD::ANY_EXTEND,Op.getValueType(),
|
2006-02-26 23:36:02 +00:00
|
|
|
Op.getOperand(0)));
|
|
|
|
|
|
|
|
// Since some of the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt InDemandedBits = InMask & NewMask;
|
2006-02-26 23:36:02 +00:00
|
|
|
InDemandedBits |= InSignBit;
|
2008-02-27 00:25:32 +00:00
|
|
|
InDemandedBits.trunc(InBits);
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedBits, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero.zext(BitWidth);
|
|
|
|
KnownOne.zext(BitWidth);
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
// If the sign bit is known zero, convert this to a zero extend.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (KnownZero.intersects(InSignBit))
|
2006-02-26 23:36:02 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ZERO_EXTEND,
|
|
|
|
Op.getValueType(),
|
|
|
|
Op.getOperand(0)));
|
|
|
|
|
|
|
|
// If the sign bit is known one, the top bits match.
|
2008-02-27 00:25:32 +00:00
|
|
|
if (KnownOne.intersects(InSignBit)) {
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Otherwise, top bits aren't known.
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::ANY_EXTEND: {
|
2008-02-27 00:25:32 +00:00
|
|
|
unsigned OperandBitWidth = Op.getOperand(0).getValueSizeInBits();
|
|
|
|
APInt InMask = NewMask;
|
|
|
|
InMask.trunc(OperandBitWidth);
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InMask,
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero.zext(BitWidth);
|
|
|
|
KnownOne.zext(BitWidth);
|
2006-02-26 23:36:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-05-05 22:32:12 +00:00
|
|
|
case ISD::TRUNCATE: {
|
2006-05-06 00:11:52 +00:00
|
|
|
// Simplify the input, using demanded bit information, and compute the known
|
|
|
|
// zero/one bits live out.
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt TruncMask = NewMask;
|
|
|
|
TruncMask.zext(Op.getOperand(0).getValueSizeInBits());
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), TruncMask,
|
2006-05-05 22:32:12 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero.trunc(BitWidth);
|
|
|
|
KnownOne.trunc(BitWidth);
|
2006-05-06 00:11:52 +00:00
|
|
|
|
|
|
|
// If the input is only used by this truncate, see if we can shrink it based
|
|
|
|
// on the known demanded bits.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (Op.getOperand(0).getNode()->hasOneUse()) {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue In = Op.getOperand(0);
|
2008-02-27 00:25:32 +00:00
|
|
|
unsigned InBitWidth = In.getValueSizeInBits();
|
2006-05-06 00:11:52 +00:00
|
|
|
switch (In.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::SRL:
|
|
|
|
// Shrink SRL by a constant if none of the high bits shifted in are
|
|
|
|
// demanded.
|
|
|
|
if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(In.getOperand(1))){
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(InBitWidth,
|
|
|
|
InBitWidth - BitWidth);
|
2008-09-12 16:56:44 +00:00
|
|
|
HighBits = HighBits.lshr(ShAmt->getZExtValue());
|
2008-02-27 00:25:32 +00:00
|
|
|
HighBits.trunc(BitWidth);
|
2006-05-06 00:11:52 +00:00
|
|
|
|
2008-09-12 16:56:44 +00:00
|
|
|
if (ShAmt->getZExtValue() < BitWidth && !(HighBits & NewMask)) {
|
2006-05-06 00:11:52 +00:00
|
|
|
// None of the shifted in bits are needed. Add a truncate of the
|
|
|
|
// shift input, then shift it.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue NewTrunc = TLO.DAG.getNode(ISD::TRUNCATE,
|
2006-05-06 00:11:52 +00:00
|
|
|
Op.getValueType(),
|
|
|
|
In.getOperand(0));
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL,Op.getValueType(),
|
|
|
|
NewTrunc, In.getOperand(1)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-05 22:32:12 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
break;
|
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
case ISD::AssertZext: {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
2008-02-27 00:25:32 +00:00
|
|
|
APInt InMask = APInt::getLowBitsSet(BitWidth,
|
2008-06-06 12:08:01 +00:00
|
|
|
VT.getSizeInBits());
|
2008-02-27 00:25:32 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InMask & NewMask,
|
2006-02-26 23:36:02 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 00:25:32 +00:00
|
|
|
KnownZero |= ~InMask & NewMask;
|
2006-02-26 23:36:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-12-22 21:35:38 +00:00
|
|
|
case ISD::BIT_CONVERT:
|
|
|
|
#if 0
|
|
|
|
// If this is an FP->Int bitcast and if the sign bit is the only thing that
|
|
|
|
// is demanded, turn this into a FGETSIGN.
|
2008-06-06 12:08:01 +00:00
|
|
|
if (NewMask == MVT::getIntegerVTSignBit(Op.getValueType()) &&
|
2007-12-22 21:35:38 +00:00
|
|
|
MVT::isFloatingPoint(Op.getOperand(0).getValueType()) &&
|
|
|
|
!MVT::isVector(Op.getOperand(0).getValueType())) {
|
|
|
|
// Only do this xform if FGETSIGN is valid or if before legalize.
|
|
|
|
if (!TLO.AfterLegalize ||
|
|
|
|
isOperationLegal(ISD::FGETSIGN, Op.getValueType())) {
|
|
|
|
// Make a FGETSIGN + SHL to move the sign bit into the appropriate
|
|
|
|
// place. We expect the SHL to be eliminated by other optimizations.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, Op.getValueType(),
|
2007-12-22 21:35:38 +00:00
|
|
|
Op.getOperand(0));
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned ShVal = Op.getValueType().getSizeInBits()-1;
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue ShAmt = TLO.DAG.getConstant(ShVal, getShiftAmountTy());
|
2007-12-22 21:35:38 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, Op.getValueType(),
|
|
|
|
Sign, ShAmt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
2008-05-06 00:53:29 +00:00
|
|
|
default:
|
2006-04-02 06:15:09 +00:00
|
|
|
// Just use ComputeMaskedBits to compute output bits.
|
2008-02-27 00:25:32 +00:00
|
|
|
TLO.DAG.ComputeMaskedBits(Op, NewMask, KnownZero, KnownOne, Depth);
|
2006-02-27 01:00:42 +00:00
|
|
|
break;
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
// If we know the value of all of the demanded bits, return this as a
|
|
|
|
// constant.
|
2008-02-27 00:25:32 +00:00
|
|
|
if ((NewMask & (KnownZero|KnownOne)) == NewMask)
|
2006-02-26 23:36:02 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType()));
|
|
|
|
|
2006-02-03 22:24:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
2006-01-30 04:09:27 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
/// computeMaskedBitsForTargetNode - Determine which of the bits specified
|
|
|
|
/// in Mask are known to be either zero or one and return them in the
|
|
|
|
/// KnownZero/KnownOne bitsets.
|
2008-07-27 21:46:04 +00:00
|
|
|
void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
2008-02-13 22:28:48 +00:00
|
|
|
const APInt &Mask,
|
2008-02-13 00:35:47 +00:00
|
|
|
APInt &KnownZero,
|
|
|
|
APInt &KnownOne,
|
2007-06-22 14:59:07 +00:00
|
|
|
const SelectionDAG &DAG,
|
2006-02-16 21:11:51 +00:00
|
|
|
unsigned Depth) const {
|
2006-04-02 06:19:46 +00:00
|
|
|
assert((Op.getOpcode() >= ISD::BUILTIN_OP_END ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
|
2006-01-30 04:09:27 +00:00
|
|
|
"Should use MaskedValueIsZero if you don't know whether Op"
|
|
|
|
" is a target node!");
|
2008-02-13 22:28:48 +00:00
|
|
|
KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
|
2005-12-21 23:05:39 +00:00
|
|
|
}
|
2006-01-26 20:37:03 +00:00
|
|
|
|
2006-05-06 09:27:13 +00:00
|
|
|
/// ComputeNumSignBitsForTargetNode - This method can be implemented by
|
|
|
|
/// targets that want to expose additional information about sign bits to the
|
|
|
|
/// DAG Combiner.
|
2008-07-27 21:46:04 +00:00
|
|
|
unsigned TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
|
2006-05-06 09:27:13 +00:00
|
|
|
unsigned Depth) const {
|
|
|
|
assert((Op.getOpcode() >= ISD::BUILTIN_OP_END ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
|
|
|
|
"Should use ComputeNumSignBits if you don't know whether Op"
|
|
|
|
" is a target node!");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-08 22:13:59 +00:00
|
|
|
/// SimplifySetCC - Try to simplify a setcc built with the specified operands
|
2008-07-27 21:46:04 +00:00
|
|
|
/// and cc. If it is unable to simplify it, return a null SDValue.
|
|
|
|
SDValue
|
|
|
|
TargetLowering::SimplifySetCC(MVT VT, SDValue N0, SDValue N1,
|
2007-02-08 22:13:59 +00:00
|
|
|
ISD::CondCode Cond, bool foldBooleans,
|
|
|
|
DAGCombinerInfo &DCI) const {
|
|
|
|
SelectionDAG &DAG = DCI.DAG;
|
|
|
|
|
|
|
|
// These setcc operations always fold.
|
|
|
|
switch (Cond) {
|
|
|
|
default: break;
|
|
|
|
case ISD::SETFALSE:
|
|
|
|
case ISD::SETFALSE2: return DAG.getConstant(0, VT);
|
|
|
|
case ISD::SETTRUE:
|
|
|
|
case ISD::SETTRUE2: return DAG.getConstant(1, VT);
|
|
|
|
}
|
|
|
|
|
2008-08-28 21:40:38 +00:00
|
|
|
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode())) {
|
2008-03-03 22:22:56 +00:00
|
|
|
const APInt &C1 = N1C->getAPIntValue();
|
2008-08-28 21:40:38 +00:00
|
|
|
if (isa<ConstantSDNode>(N0.getNode())) {
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.FoldSetCC(VT, N0, N1, Cond);
|
|
|
|
} else {
|
|
|
|
// If the LHS is '(srl (ctlz x), 5)', the RHS is 0/1, and this is an
|
|
|
|
// equality comparison, then we're just comparing whether X itself is
|
|
|
|
// zero.
|
|
|
|
if (N0.getOpcode() == ISD::SRL && (C1 == 0 || C1 == 1) &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::CTLZ &&
|
|
|
|
N0.getOperand(1).getOpcode() == ISD::Constant) {
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned ShAmt = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
|
2007-02-08 22:13:59 +00:00
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
2008-06-06 12:08:01 +00:00
|
|
|
ShAmt == Log2_32(N0.getValueType().getSizeInBits())) {
|
2007-02-08 22:13:59 +00:00
|
|
|
if ((C1 == 0) == (Cond == ISD::SETEQ)) {
|
|
|
|
// (srl (ctlz x), 5) == 0 -> X != 0
|
|
|
|
// (srl (ctlz x), 5) != 1 -> X != 0
|
|
|
|
Cond = ISD::SETNE;
|
|
|
|
} else {
|
|
|
|
// (srl (ctlz x), 5) != 0 -> X == 0
|
|
|
|
// (srl (ctlz x), 5) == 1 -> X == 0
|
|
|
|
Cond = ISD::SETEQ;
|
|
|
|
}
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Zero = DAG.getConstant(0, N0.getValueType());
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0).getOperand(0),
|
|
|
|
Zero, Cond);
|
|
|
|
}
|
|
|
|
}
|
2008-11-07 01:28:02 +00:00
|
|
|
|
|
|
|
// If the LHS is '(and load, const)', the RHS is 0,
|
|
|
|
// the test is for equality or unsigned, and all 1 bits of the const are
|
|
|
|
// in the same partial word, see if we can shorten the load.
|
|
|
|
if (DCI.isBeforeLegalize() &&
|
|
|
|
N0.getOpcode() == ISD::AND && C1 == 0 &&
|
|
|
|
isa<LoadSDNode>(N0.getOperand(0)) &&
|
|
|
|
N0.getOperand(0).getNode()->hasOneUse() &&
|
|
|
|
isa<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
LoadSDNode *Lod = cast<LoadSDNode>(N0.getOperand(0));
|
|
|
|
uint64_t Mask = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
|
2008-11-10 07:16:42 +00:00
|
|
|
uint64_t bestMask = 0;
|
2008-11-07 01:28:02 +00:00
|
|
|
unsigned bestWidth = 0, bestOffset = 0;
|
2008-11-10 07:16:42 +00:00
|
|
|
if (!Lod->isVolatile() && Lod->isUnindexed()) {
|
2008-11-07 01:28:02 +00:00
|
|
|
unsigned origWidth = N0.getValueType().getSizeInBits();
|
2008-11-10 07:16:42 +00:00
|
|
|
// We can narrow (e.g.) 16-bit extending loads on 32-bit target to
|
|
|
|
// 8 bits, but have to be careful...
|
|
|
|
if (Lod->getExtensionType() != ISD::NON_EXTLOAD)
|
|
|
|
origWidth = Lod->getMemoryVT().getSizeInBits();
|
2008-11-07 01:28:02 +00:00
|
|
|
for (unsigned width = origWidth / 2; width>=8; width /= 2) {
|
|
|
|
uint64_t newMask = (1ULL << width) - 1;
|
|
|
|
for (unsigned offset=0; offset<origWidth/width; offset++) {
|
|
|
|
if ((newMask & Mask)==Mask) {
|
2008-11-08 00:01:16 +00:00
|
|
|
if (!TD->isLittleEndian())
|
|
|
|
bestOffset = (origWidth/width - offset - 1) * (width/8);
|
2008-11-10 07:16:42 +00:00
|
|
|
else
|
2008-11-08 00:01:16 +00:00
|
|
|
bestOffset = (uint64_t)offset * (width/8);
|
2008-11-12 02:00:35 +00:00
|
|
|
bestMask = Mask >> (offset * (width/8) * 8);
|
2008-11-07 01:28:02 +00:00
|
|
|
bestWidth = width;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
newMask = newMask << width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bestWidth) {
|
|
|
|
MVT newVT = MVT::getIntegerVT(bestWidth);
|
|
|
|
if (newVT.isRound()) {
|
|
|
|
MVT PtrType = Lod->getOperand(1).getValueType();
|
|
|
|
SDValue Ptr = Lod->getBasePtr();
|
|
|
|
if (bestOffset != 0)
|
|
|
|
Ptr = DAG.getNode(ISD::ADD, PtrType, Lod->getBasePtr(),
|
|
|
|
DAG.getConstant(bestOffset, PtrType));
|
|
|
|
unsigned NewAlign = MinAlign(Lod->getAlignment(), bestOffset);
|
|
|
|
SDValue NewLoad = DAG.getLoad(newVT, Lod->getChain(), Ptr,
|
|
|
|
Lod->getSrcValue(),
|
|
|
|
Lod->getSrcValueOffset() + bestOffset,
|
|
|
|
false, NewAlign);
|
|
|
|
return DAG.getSetCC(VT, DAG.getNode(ISD::AND, newVT, NewLoad,
|
|
|
|
DAG.getConstant(bestMask, newVT)),
|
|
|
|
DAG.getConstant(0LL, newVT), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-11-10 21:22:06 +00:00
|
|
|
|
2007-02-08 22:13:59 +00:00
|
|
|
// If the LHS is a ZERO_EXTEND, perform the comparison on the input.
|
|
|
|
if (N0.getOpcode() == ISD::ZERO_EXTEND) {
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned InSize = N0.getOperand(0).getValueType().getSizeInBits();
|
2007-02-08 22:13:59 +00:00
|
|
|
|
|
|
|
// If the comparison constant has bits in the upper part, the
|
|
|
|
// zero-extended value could never match.
|
2008-03-03 22:22:56 +00:00
|
|
|
if (C1.intersects(APInt::getHighBitsSet(C1.getBitWidth(),
|
|
|
|
C1.getBitWidth() - InSize))) {
|
2007-02-08 22:13:59 +00:00
|
|
|
switch (Cond) {
|
|
|
|
case ISD::SETUGT:
|
|
|
|
case ISD::SETUGE:
|
|
|
|
case ISD::SETEQ: return DAG.getConstant(0, VT);
|
|
|
|
case ISD::SETULT:
|
|
|
|
case ISD::SETULE:
|
|
|
|
case ISD::SETNE: return DAG.getConstant(1, VT);
|
|
|
|
case ISD::SETGT:
|
|
|
|
case ISD::SETGE:
|
|
|
|
// True if the sign bit of C1 is set.
|
2008-03-03 22:22:56 +00:00
|
|
|
return DAG.getConstant(C1.isNegative(), VT);
|
2007-02-08 22:13:59 +00:00
|
|
|
case ISD::SETLT:
|
|
|
|
case ISD::SETLE:
|
|
|
|
// True if the sign bit of C1 isn't set.
|
2008-03-03 22:22:56 +00:00
|
|
|
return DAG.getConstant(C1.isNonNegative(), VT);
|
2007-02-08 22:13:59 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we can perform the comparison with the low bits.
|
|
|
|
switch (Cond) {
|
|
|
|
case ISD::SETEQ:
|
|
|
|
case ISD::SETNE:
|
|
|
|
case ISD::SETUGT:
|
|
|
|
case ISD::SETUGE:
|
|
|
|
case ISD::SETULT:
|
|
|
|
case ISD::SETULE:
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
2008-03-03 22:22:56 +00:00
|
|
|
DAG.getConstant(APInt(C1).trunc(InSize),
|
|
|
|
N0.getOperand(0).getValueType()),
|
2007-02-08 22:13:59 +00:00
|
|
|
Cond);
|
|
|
|
default:
|
|
|
|
break; // todo, be more careful with signed comparisons
|
|
|
|
}
|
|
|
|
} else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
|
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT ExtSrcTy = cast<VTSDNode>(N0.getOperand(1))->getVT();
|
|
|
|
unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits();
|
|
|
|
MVT ExtDstTy = N0.getValueType();
|
|
|
|
unsigned ExtDstTyBits = ExtDstTy.getSizeInBits();
|
2007-02-08 22:13:59 +00:00
|
|
|
|
|
|
|
// If the extended part has any inconsistent bits, it cannot ever
|
|
|
|
// compare equal. In other words, they have to be all ones or all
|
|
|
|
// zeros.
|
2008-03-03 22:22:56 +00:00
|
|
|
APInt ExtBits =
|
|
|
|
APInt::getHighBitsSet(ExtDstTyBits, ExtDstTyBits - ExtSrcTyBits);
|
2007-02-08 22:13:59 +00:00
|
|
|
if ((C1 & ExtBits) != 0 && (C1 & ExtBits) != ExtBits)
|
|
|
|
return DAG.getConstant(Cond == ISD::SETNE, VT);
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue ZextOp;
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT Op0Ty = N0.getOperand(0).getValueType();
|
2007-02-08 22:13:59 +00:00
|
|
|
if (Op0Ty == ExtSrcTy) {
|
|
|
|
ZextOp = N0.getOperand(0);
|
|
|
|
} else {
|
2008-03-03 22:37:52 +00:00
|
|
|
APInt Imm = APInt::getLowBitsSet(ExtDstTyBits, ExtSrcTyBits);
|
2007-02-08 22:13:59 +00:00
|
|
|
ZextOp = DAG.getNode(ISD::AND, Op0Ty, N0.getOperand(0),
|
|
|
|
DAG.getConstant(Imm, Op0Ty));
|
|
|
|
}
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(ZextOp.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
// Otherwise, make this a use of a zext.
|
|
|
|
return DAG.getSetCC(VT, ZextOp,
|
2008-03-03 22:22:56 +00:00
|
|
|
DAG.getConstant(C1 & APInt::getLowBitsSet(
|
|
|
|
ExtDstTyBits,
|
|
|
|
ExtSrcTyBits),
|
2007-02-08 22:13:59 +00:00
|
|
|
ExtDstTy),
|
|
|
|
Cond);
|
2008-03-03 22:22:56 +00:00
|
|
|
} else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) &&
|
2007-02-08 22:13:59 +00:00
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
|
|
|
|
|
|
|
// SETCC (SETCC), [0|1], [EQ|NE] -> SETCC
|
|
|
|
if (N0.getOpcode() == ISD::SETCC) {
|
2008-09-12 16:56:44 +00:00
|
|
|
bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getZExtValue() != 1);
|
2007-02-08 22:13:59 +00:00
|
|
|
if (TrueWhenTrue)
|
|
|
|
return N0;
|
|
|
|
|
|
|
|
// Invert the condition.
|
|
|
|
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
|
|
|
|
CC = ISD::getSetCCInverse(CC,
|
2008-06-06 12:08:01 +00:00
|
|
|
N0.getOperand(0).getValueType().isInteger());
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N0.getOperand(1), CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((N0.getOpcode() == ISD::XOR ||
|
|
|
|
(N0.getOpcode() == ISD::AND &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR &&
|
|
|
|
N0.getOperand(1) == N0.getOperand(0).getOperand(1))) &&
|
|
|
|
isa<ConstantSDNode>(N0.getOperand(1)) &&
|
2008-03-13 22:13:53 +00:00
|
|
|
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue() == 1) {
|
2007-02-08 22:13:59 +00:00
|
|
|
// If this is (X^1) == 0/1, swap the RHS and eliminate the xor. We
|
|
|
|
// can only do this if the top bits are known zero.
|
2008-02-25 21:11:39 +00:00
|
|
|
unsigned BitWidth = N0.getValueSizeInBits();
|
2007-06-22 14:59:07 +00:00
|
|
|
if (DAG.MaskedValueIsZero(N0,
|
2008-02-25 21:11:39 +00:00
|
|
|
APInt::getHighBitsSet(BitWidth,
|
|
|
|
BitWidth-1))) {
|
2007-02-08 22:13:59 +00:00
|
|
|
// Okay, get the un-inverted input value.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Val;
|
2007-02-08 22:13:59 +00:00
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
Val = N0.getOperand(0);
|
|
|
|
else {
|
|
|
|
assert(N0.getOpcode() == ISD::AND &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR);
|
|
|
|
// ((X^1)&1)^1 -> X & 1
|
|
|
|
Val = DAG.getNode(ISD::AND, N0.getValueType(),
|
|
|
|
N0.getOperand(0).getOperand(0),
|
|
|
|
N0.getOperand(1));
|
|
|
|
}
|
|
|
|
return DAG.getSetCC(VT, Val, N1,
|
|
|
|
Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-03 22:37:52 +00:00
|
|
|
APInt MinVal, MaxVal;
|
2008-06-06 12:08:01 +00:00
|
|
|
unsigned OperandBitSize = N1C->getValueType(0).getSizeInBits();
|
2007-02-08 22:13:59 +00:00
|
|
|
if (ISD::isSignedIntSetCC(Cond)) {
|
2008-03-03 22:37:52 +00:00
|
|
|
MinVal = APInt::getSignedMinValue(OperandBitSize);
|
|
|
|
MaxVal = APInt::getSignedMaxValue(OperandBitSize);
|
2007-02-08 22:13:59 +00:00
|
|
|
} else {
|
2008-03-03 22:37:52 +00:00
|
|
|
MinVal = APInt::getMinValue(OperandBitSize);
|
|
|
|
MaxVal = APInt::getMaxValue(OperandBitSize);
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Canonicalize GE/LE comparisons to use GT/LT comparisons.
|
|
|
|
if (Cond == ISD::SETGE || Cond == ISD::SETUGE) {
|
|
|
|
if (C1 == MinVal) return DAG.getConstant(1, VT); // X >= MIN --> true
|
2008-03-03 22:22:56 +00:00
|
|
|
// X >= C0 --> X > (C0-1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(C1-1, N1.getValueType()),
|
2007-02-08 22:13:59 +00:00
|
|
|
(Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Cond == ISD::SETLE || Cond == ISD::SETULE) {
|
|
|
|
if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true
|
2008-03-03 22:22:56 +00:00
|
|
|
// X <= C0 --> X < (C0+1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(C1+1, N1.getValueType()),
|
2007-02-08 22:13:59 +00:00
|
|
|
(Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal)
|
|
|
|
return DAG.getConstant(0, VT); // X < MIN --> false
|
|
|
|
if ((Cond == ISD::SETGE || Cond == ISD::SETUGE) && C1 == MinVal)
|
|
|
|
return DAG.getConstant(1, VT); // X >= MIN --> true
|
|
|
|
if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal)
|
|
|
|
return DAG.getConstant(0, VT); // X > MAX --> false
|
|
|
|
if ((Cond == ISD::SETLE || Cond == ISD::SETULE) && C1 == MaxVal)
|
|
|
|
return DAG.getConstant(1, VT); // X <= MAX --> true
|
|
|
|
|
|
|
|
// Canonicalize setgt X, Min --> setne X, Min
|
|
|
|
if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MinVal)
|
|
|
|
return DAG.getSetCC(VT, N0, N1, ISD::SETNE);
|
|
|
|
// Canonicalize setlt X, Max --> setne X, Max
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MaxVal)
|
|
|
|
return DAG.getSetCC(VT, N0, N1, ISD::SETNE);
|
|
|
|
|
|
|
|
// If we have setult X, 1, turn it into seteq X, 0
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal+1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(MinVal, N0.getValueType()),
|
|
|
|
ISD::SETEQ);
|
|
|
|
// If we have setugt X, Max-1, turn it into seteq X, Max
|
|
|
|
else if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(MaxVal, N0.getValueType()),
|
|
|
|
ISD::SETEQ);
|
|
|
|
|
|
|
|
// If we have "setcc X, C0", check to see if we can shrink the immediate
|
|
|
|
// by changing cc.
|
|
|
|
|
|
|
|
// SETUGT X, SINTMAX -> SETLT X, 0
|
2008-11-30 04:59:26 +00:00
|
|
|
if (Cond == ISD::SETUGT &&
|
|
|
|
C1 == APInt::getSignedMaxValue(OperandBitSize))
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(0, N1.getValueType()),
|
|
|
|
ISD::SETLT);
|
|
|
|
|
2008-11-30 04:59:26 +00:00
|
|
|
// SETULT X, SINTMIN -> SETGT X, -1
|
|
|
|
if (Cond == ISD::SETULT &&
|
|
|
|
C1 == APInt::getSignedMinValue(OperandBitSize)) {
|
|
|
|
SDValue ConstMinusOne =
|
|
|
|
DAG.getConstant(APInt::getAllOnesValue(OperandBitSize),
|
|
|
|
N1.getValueType());
|
|
|
|
return DAG.getSetCC(VT, N0, ConstMinusOne, ISD::SETGT);
|
|
|
|
}
|
2007-02-08 22:13:59 +00:00
|
|
|
|
|
|
|
// Fold bit comparisons when we can.
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
VT == N0.getValueType() && N0.getOpcode() == ISD::AND)
|
|
|
|
if (ConstantSDNode *AndRHS =
|
|
|
|
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if the AND RHS is a single bit.
|
2008-09-12 16:56:44 +00:00
|
|
|
if (isPowerOf2_64(AndRHS->getZExtValue())) {
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getNode(ISD::SRL, VT, N0,
|
2008-09-12 16:56:44 +00:00
|
|
|
DAG.getConstant(Log2_64(AndRHS->getZExtValue()),
|
2007-02-08 22:13:59 +00:00
|
|
|
getShiftAmountTy()));
|
|
|
|
}
|
2008-09-12 16:56:44 +00:00
|
|
|
} else if (Cond == ISD::SETEQ && C1 == AndRHS->getZExtValue()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
// (X & 8) == 8 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if C1 is a single bit.
|
2008-03-03 22:22:56 +00:00
|
|
|
if (C1.isPowerOf2()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getNode(ISD::SRL, VT, N0,
|
2008-03-03 22:22:56 +00:00
|
|
|
DAG.getConstant(C1.logBase2(), getShiftAmountTy()));
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-28 21:40:38 +00:00
|
|
|
} else if (isa<ConstantSDNode>(N0.getNode())) {
|
2007-02-08 22:13:59 +00:00
|
|
|
// Ensure that the constant occurs on the RHS.
|
|
|
|
return DAG.getSetCC(VT, N1, N0, ISD::getSetCCSwappedOperands(Cond));
|
|
|
|
}
|
|
|
|
|
2008-08-28 21:40:38 +00:00
|
|
|
if (isa<ConstantFPSDNode>(N0.getNode())) {
|
2007-02-08 22:13:59 +00:00
|
|
|
// Constant fold or commute setcc.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue O = DAG.FoldSetCC(VT, N0, N1, Cond);
|
2008-08-28 21:40:38 +00:00
|
|
|
if (O.getNode()) return O;
|
|
|
|
} else if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N1.getNode())) {
|
Fold comparisons against a constant nan, and optimize ORD/UNORD
comparisons with a constant. This allows us to compile isnan to:
_foo:
fcmpu cr7, f1, f1
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr
instead of:
LCPI1_0: ; float
.space 4
_foo:
lis r2, ha16(LCPI1_0)
lfs f0, lo16(LCPI1_0)(r2)
fcmpu cr7, f1, f0
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45405 91177308-0d34-0410-b5e6-96231b3b80d8
2007-12-29 08:37:08 +00:00
|
|
|
// If the RHS of an FP comparison is a constant, simplify it away in
|
|
|
|
// some cases.
|
|
|
|
if (CFP->getValueAPF().isNaN()) {
|
|
|
|
// If an operand is known to be a nan, we can fold it.
|
|
|
|
switch (ISD::getUnorderedFlavor(Cond)) {
|
|
|
|
default: assert(0 && "Unknown flavor!");
|
|
|
|
case 0: // Known false.
|
|
|
|
return DAG.getConstant(0, VT);
|
|
|
|
case 1: // Known true.
|
|
|
|
return DAG.getConstant(1, VT);
|
2007-12-30 21:21:10 +00:00
|
|
|
case 2: // Undefined.
|
Fold comparisons against a constant nan, and optimize ORD/UNORD
comparisons with a constant. This allows us to compile isnan to:
_foo:
fcmpu cr7, f1, f1
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr
instead of:
LCPI1_0: ; float
.space 4
_foo:
lis r2, ha16(LCPI1_0)
lfs f0, lo16(LCPI1_0)(r2)
fcmpu cr7, f1, f0
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45405 91177308-0d34-0410-b5e6-96231b3b80d8
2007-12-29 08:37:08 +00:00
|
|
|
return DAG.getNode(ISD::UNDEF, VT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we know the RHS is not a NaN. Simplify the node to drop the
|
|
|
|
// constant if knowing that the operand is non-nan is enough. We prefer to
|
|
|
|
// have SETO(x,x) instead of SETO(x, 0.0) because this avoids having to
|
|
|
|
// materialize 0.0.
|
|
|
|
if (Cond == ISD::SETO || Cond == ISD::SETUO)
|
|
|
|
return DAG.getSetCC(VT, N0, N0, Cond);
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (N0 == N1) {
|
|
|
|
// We can always fold X == X for integer setcc's.
|
2008-06-06 12:08:01 +00:00
|
|
|
if (N0.getValueType().isInteger())
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT);
|
|
|
|
unsigned UOF = ISD::getUnorderedFlavor(Cond);
|
|
|
|
if (UOF == 2) // FP operators that are undefined on NaNs.
|
|
|
|
return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT);
|
|
|
|
if (UOF == unsigned(ISD::isTrueWhenEqual(Cond)))
|
|
|
|
return DAG.getConstant(UOF, VT);
|
|
|
|
// Otherwise, we can't fold it. However, we can simplify it to SETUO/SETO
|
|
|
|
// if it is not already.
|
|
|
|
ISD::CondCode NewCond = UOF == 0 ? ISD::SETO : ISD::SETUO;
|
|
|
|
if (NewCond != Cond)
|
|
|
|
return DAG.getSetCC(VT, N0, N1, NewCond);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
2008-06-06 12:08:01 +00:00
|
|
|
N0.getValueType().isInteger()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
if (N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB ||
|
|
|
|
N0.getOpcode() == ISD::XOR) {
|
|
|
|
// Simplify (X+Y) == (X+Z) --> Y == Z
|
|
|
|
if (N0.getOpcode() == N1.getOpcode()) {
|
|
|
|
if (N0.getOperand(0) == N1.getOperand(0))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(1), Cond);
|
|
|
|
if (N0.getOperand(1) == N1.getOperand(1))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N1.getOperand(0), Cond);
|
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode())) {
|
|
|
|
// If X op Y == Y op X, try other combinations.
|
|
|
|
if (N0.getOperand(0) == N1.getOperand(1))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(0), Cond);
|
|
|
|
if (N0.getOperand(1) == N1.getOperand(0))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N1.getOperand(1), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(N1)) {
|
|
|
|
if (ConstantSDNode *LHSR = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
// Turn (X+C1) == C2 --> X == C2-C1
|
2008-08-28 21:40:38 +00:00
|
|
|
if (N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
2008-09-12 16:56:44 +00:00
|
|
|
DAG.getConstant(RHSC->getAPIntValue()-
|
|
|
|
LHSR->getAPIntValue(),
|
2007-02-08 22:13:59 +00:00
|
|
|
N0.getValueType()), Cond);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0.
|
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
// If we know that all of the inverted bits are zero, don't bother
|
|
|
|
// performing the inversion.
|
2008-02-25 21:11:39 +00:00
|
|
|
if (DAG.MaskedValueIsZero(N0.getOperand(0), ~LHSR->getAPIntValue()))
|
|
|
|
return
|
|
|
|
DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(LHSR->getAPIntValue() ^
|
|
|
|
RHSC->getAPIntValue(),
|
|
|
|
N0.getValueType()),
|
|
|
|
Cond);
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Turn (C1-X) == C2 --> X == C1-C2
|
|
|
|
if (ConstantSDNode *SUBC = dyn_cast<ConstantSDNode>(N0.getOperand(0))) {
|
2008-08-28 21:40:38 +00:00
|
|
|
if (N0.getOpcode() == ISD::SUB && N0.getNode()->hasOneUse()) {
|
2008-02-25 21:11:39 +00:00
|
|
|
return
|
|
|
|
DAG.getSetCC(VT, N0.getOperand(1),
|
|
|
|
DAG.getConstant(SUBC->getAPIntValue() -
|
|
|
|
RHSC->getAPIntValue(),
|
|
|
|
N0.getValueType()),
|
|
|
|
Cond);
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simplify (X+Z) == X --> Z == 0
|
|
|
|
if (N0.getOperand(0) == N1)
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
|
|
|
if (N0.getOperand(1) == N1) {
|
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode()))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
2008-08-28 21:40:38 +00:00
|
|
|
else if (N0.getNode()->hasOneUse()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// (Z-X) == X --> Z == X<<1
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue SH = DAG.getNode(ISD::SHL, N1.getValueType(),
|
2007-02-08 22:13:59 +00:00
|
|
|
N1,
|
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(SH.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), SH, Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB ||
|
|
|
|
N1.getOpcode() == ISD::XOR) {
|
|
|
|
// Simplify X == (X+Z) --> Z == 0
|
|
|
|
if (N1.getOperand(0) == N0) {
|
|
|
|
return DAG.getSetCC(VT, N1.getOperand(1),
|
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
|
|
|
} else if (N1.getOperand(1) == N0) {
|
|
|
|
if (DAG.isCommutativeBinOp(N1.getOpcode())) {
|
|
|
|
return DAG.getSetCC(VT, N1.getOperand(0),
|
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
2008-08-28 21:40:38 +00:00
|
|
|
} else if (N1.getNode()->hasOneUse()) {
|
2007-02-08 22:13:59 +00:00
|
|
|
assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// X == (Z-X) --> X<<1 == Z
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue SH = DAG.getNode(ISD::SHL, N1.getValueType(), N0,
|
2007-02-08 22:13:59 +00:00
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(SH.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
return DAG.getSetCC(VT, SH, N1.getOperand(0), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fold away ALL boolean setcc's.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Temp;
|
2007-02-08 22:13:59 +00:00
|
|
|
if (N0.getValueType() == MVT::i1 && foldBooleans) {
|
|
|
|
switch (Cond) {
|
|
|
|
default: assert(0 && "Unknown integer setcc!");
|
|
|
|
case ISD::SETEQ: // X == Y -> (X^Y)^1
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, N1);
|
|
|
|
N0 = DAG.getNode(ISD::XOR, MVT::i1, Temp, DAG.getConstant(1, MVT::i1));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
break;
|
|
|
|
case ISD::SETNE: // X != Y --> (X^Y)
|
|
|
|
N0 = DAG.getNode(ISD::XOR, MVT::i1, N0, N1);
|
|
|
|
break;
|
|
|
|
case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> X^1 & Y
|
|
|
|
case ISD::SETULT: // X <u Y --> X == 0 & Y == 1 --> X^1 & Y
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::AND, MVT::i1, N1, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
break;
|
|
|
|
case ISD::SETLT: // X <s Y --> X == 1 & Y == 0 --> Y^1 & X
|
|
|
|
case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> Y^1 & X
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::AND, MVT::i1, N0, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
break;
|
|
|
|
case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> X^1 | Y
|
|
|
|
case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> X^1 | Y
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::OR, MVT::i1, N1, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
break;
|
|
|
|
case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> Y^1 | X
|
|
|
|
case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> Y^1 | X
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::OR, MVT::i1, N0, Temp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (VT != MVT::i1) {
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-28 21:40:38 +00:00
|
|
|
DCI.AddToWorklist(N0.getNode());
|
2007-02-08 22:13:59 +00:00
|
|
|
// FIXME: If running after legalize, we probably can't do this.
|
|
|
|
N0 = DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
|
|
|
|
}
|
|
|
|
return N0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Could not fold it.
|
2008-07-27 21:46:04 +00:00
|
|
|
return SDValue();
|
2007-02-08 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 19:56:52 +00:00
|
|
|
/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the
|
|
|
|
/// node is a GlobalAddress + offset.
|
|
|
|
bool TargetLowering::isGAPlusOffset(SDNode *N, GlobalValue* &GA,
|
|
|
|
int64_t &Offset) const {
|
|
|
|
if (isa<GlobalAddressSDNode>(N)) {
|
2008-06-09 22:05:52 +00:00
|
|
|
GlobalAddressSDNode *GASD = cast<GlobalAddressSDNode>(N);
|
|
|
|
GA = GASD->getGlobal();
|
|
|
|
Offset += GASD->getOffset();
|
2008-05-12 19:56:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N->getOpcode() == ISD::ADD) {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue N1 = N->getOperand(0);
|
|
|
|
SDValue N2 = N->getOperand(1);
|
2008-08-28 21:40:38 +00:00
|
|
|
if (isGAPlusOffset(N1.getNode(), GA, Offset)) {
|
2008-05-12 19:56:52 +00:00
|
|
|
ConstantSDNode *V = dyn_cast<ConstantSDNode>(N2);
|
|
|
|
if (V) {
|
2008-09-26 21:54:37 +00:00
|
|
|
Offset += V->getSExtValue();
|
2008-05-12 19:56:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
2008-08-28 21:40:38 +00:00
|
|
|
} else if (isGAPlusOffset(N2.getNode(), GA, Offset)) {
|
2008-05-12 19:56:52 +00:00
|
|
|
ConstantSDNode *V = dyn_cast<ConstantSDNode>(N1);
|
|
|
|
if (V) {
|
2008-09-26 21:54:37 +00:00
|
|
|
Offset += V->getSExtValue();
|
2008-05-12 19:56:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// isConsecutiveLoad - Return true if LD (which must be a LoadSDNode) is
|
|
|
|
/// loading 'Bytes' bytes from a location that is 'Dist' units away from the
|
|
|
|
/// location that the 'Base' load is loading from.
|
|
|
|
bool TargetLowering::isConsecutiveLoad(SDNode *LD, SDNode *Base,
|
|
|
|
unsigned Bytes, int Dist,
|
2008-05-12 23:04:07 +00:00
|
|
|
const MachineFrameInfo *MFI) const {
|
2008-08-28 21:40:38 +00:00
|
|
|
if (LD->getOperand(0).getNode() != Base->getOperand(0).getNode())
|
2008-05-12 19:56:52 +00:00
|
|
|
return false;
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = LD->getValueType(0);
|
|
|
|
if (VT.getSizeInBits() / 8 != Bytes)
|
2008-05-12 19:56:52 +00:00
|
|
|
return false;
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Loc = LD->getOperand(1);
|
|
|
|
SDValue BaseLoc = Base->getOperand(1);
|
2008-05-12 19:56:52 +00:00
|
|
|
if (Loc.getOpcode() == ISD::FrameIndex) {
|
|
|
|
if (BaseLoc.getOpcode() != ISD::FrameIndex)
|
|
|
|
return false;
|
|
|
|
int FI = cast<FrameIndexSDNode>(Loc)->getIndex();
|
|
|
|
int BFI = cast<FrameIndexSDNode>(BaseLoc)->getIndex();
|
|
|
|
int FS = MFI->getObjectSize(FI);
|
|
|
|
int BFS = MFI->getObjectSize(BFI);
|
|
|
|
if (FS != BFS || FS != (int)Bytes) return false;
|
|
|
|
return MFI->getObjectOffset(FI) == (MFI->getObjectOffset(BFI) + Dist*Bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalValue *GV1 = NULL;
|
|
|
|
GlobalValue *GV2 = NULL;
|
|
|
|
int64_t Offset1 = 0;
|
|
|
|
int64_t Offset2 = 0;
|
2008-08-28 21:40:38 +00:00
|
|
|
bool isGA1 = isGAPlusOffset(Loc.getNode(), GV1, Offset1);
|
|
|
|
bool isGA2 = isGAPlusOffset(BaseLoc.getNode(), GV2, Offset2);
|
2008-05-12 19:56:52 +00:00
|
|
|
if (isGA1 && isGA2 && GV1 == GV2)
|
|
|
|
return Offset1 == (Offset2 + Dist*Bytes);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue TargetLowering::
|
2006-03-01 04:52:55 +00:00
|
|
|
PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
|
|
|
// Default implementation: no optimization.
|
2008-07-27 21:46:04 +00:00
|
|
|
return SDValue();
|
2006-03-01 04:52:55 +00:00
|
|
|
}
|
|
|
|
|
2006-02-04 02:13:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Inline Assembler Implementation Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-04-27 00:09:47 +00:00
|
|
|
|
2006-02-04 02:13:02 +00:00
|
|
|
TargetLowering::ConstraintType
|
2007-03-25 02:14:49 +00:00
|
|
|
TargetLowering::getConstraintType(const std::string &Constraint) const {
|
2006-02-04 02:13:02 +00:00
|
|
|
// FIXME: lots more standard ones to handle.
|
2007-03-25 02:14:49 +00:00
|
|
|
if (Constraint.size() == 1) {
|
|
|
|
switch (Constraint[0]) {
|
|
|
|
default: break;
|
|
|
|
case 'r': return C_RegisterClass;
|
|
|
|
case 'm': // memory
|
|
|
|
case 'o': // offsetable
|
|
|
|
case 'V': // not offsetable
|
|
|
|
return C_Memory;
|
|
|
|
case 'i': // Simple Integer or Relocatable Constant
|
|
|
|
case 'n': // Simple Integer
|
|
|
|
case 's': // Relocatable Constant
|
2007-03-25 04:35:41 +00:00
|
|
|
case 'X': // Allow ANY value.
|
2007-03-25 02:14:49 +00:00
|
|
|
case 'I': // Target registers.
|
|
|
|
case 'J':
|
|
|
|
case 'K':
|
|
|
|
case 'L':
|
|
|
|
case 'M':
|
|
|
|
case 'N':
|
|
|
|
case 'O':
|
|
|
|
case 'P':
|
|
|
|
return C_Other;
|
|
|
|
}
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
2007-03-25 02:18:14 +00:00
|
|
|
|
|
|
|
if (Constraint.size() > 1 && Constraint[0] == '{' &&
|
|
|
|
Constraint[Constraint.size()-1] == '}')
|
|
|
|
return C_Register;
|
2007-03-25 02:14:49 +00:00
|
|
|
return C_Unknown;
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
|
|
|
|
2008-01-29 02:21:21 +00:00
|
|
|
/// LowerXConstraint - try to replace an X constraint, which matches anything,
|
|
|
|
/// with another that has more specific requirements based on the type of the
|
|
|
|
/// corresponding operand.
|
2008-06-06 12:08:01 +00:00
|
|
|
const char *TargetLowering::LowerXConstraint(MVT ConstraintVT) const{
|
|
|
|
if (ConstraintVT.isInteger())
|
2008-04-26 23:02:14 +00:00
|
|
|
return "r";
|
2008-06-06 12:08:01 +00:00
|
|
|
if (ConstraintVT.isFloatingPoint())
|
2008-04-26 23:02:14 +00:00
|
|
|
return "f"; // works for many targets
|
|
|
|
return 0;
|
2008-01-29 02:21:21 +00:00
|
|
|
}
|
|
|
|
|
2007-08-25 00:47:38 +00:00
|
|
|
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
|
|
|
|
/// vector. If it is invalid, don't add anything to Ops.
|
2008-07-27 21:46:04 +00:00
|
|
|
void TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
|
2007-08-25 00:47:38 +00:00
|
|
|
char ConstraintLetter,
|
2008-09-24 00:05:32 +00:00
|
|
|
bool hasMemory,
|
2008-07-27 21:46:04 +00:00
|
|
|
std::vector<SDValue> &Ops,
|
2008-04-26 23:02:14 +00:00
|
|
|
SelectionDAG &DAG) const {
|
2006-02-04 02:13:02 +00:00
|
|
|
switch (ConstraintLetter) {
|
2007-02-17 06:00:35 +00:00
|
|
|
default: break;
|
2007-11-05 21:20:28 +00:00
|
|
|
case 'X': // Allows any operand; labels (basic block) use this.
|
|
|
|
if (Op.getOpcode() == ISD::BasicBlock) {
|
|
|
|
Ops.push_back(Op);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fall through
|
2006-02-04 02:13:02 +00:00
|
|
|
case 'i': // Simple Integer or Relocatable Constant
|
|
|
|
case 'n': // Simple Integer
|
2007-11-05 21:20:28 +00:00
|
|
|
case 's': { // Relocatable Constant
|
2007-05-03 16:54:34 +00:00
|
|
|
// These operands are interested in values of the form (GV+C), where C may
|
|
|
|
// be folded in as an offset of GV, or it may be explicitly added. Also, it
|
|
|
|
// is possible and fine if either GV or C are missing.
|
|
|
|
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
|
|
|
|
GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
|
|
|
|
|
|
|
|
// If we have "(add GV, C)", pull out GV/C
|
|
|
|
if (Op.getOpcode() == ISD::ADD) {
|
|
|
|
C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
|
|
|
|
GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
|
|
|
|
if (C == 0 || GA == 0) {
|
|
|
|
C = dyn_cast<ConstantSDNode>(Op.getOperand(0));
|
|
|
|
GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(1));
|
|
|
|
}
|
|
|
|
if (C == 0 || GA == 0)
|
|
|
|
C = 0, GA = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we find a valid operand, map to the TargetXXX version so that the
|
|
|
|
// value itself doesn't get selected.
|
|
|
|
if (GA) { // Either &GV or &GV+C
|
|
|
|
if (ConstraintLetter != 'n') {
|
|
|
|
int64_t Offs = GA->getOffset();
|
2008-09-12 16:56:44 +00:00
|
|
|
if (C) Offs += C->getZExtValue();
|
2007-08-25 00:47:38 +00:00
|
|
|
Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(),
|
|
|
|
Op.getValueType(), Offs));
|
|
|
|
return;
|
2007-05-03 16:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (C) { // just C, no GV.
|
2007-02-17 06:00:35 +00:00
|
|
|
// Simple constants are not allowed for 's'.
|
2007-08-25 00:47:38 +00:00
|
|
|
if (ConstraintLetter != 's') {
|
2008-09-12 16:56:44 +00:00
|
|
|
Ops.push_back(DAG.getTargetConstant(C->getAPIntValue(),
|
|
|
|
Op.getValueType()));
|
2007-08-25 00:47:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-02-17 06:00:35 +00:00
|
|
|
}
|
|
|
|
break;
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
2007-05-03 16:54:34 +00:00
|
|
|
}
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
|
|
|
|
2006-01-26 20:37:03 +00:00
|
|
|
std::vector<unsigned> TargetLowering::
|
2006-02-22 00:56:39 +00:00
|
|
|
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT) const {
|
2006-02-22 00:56:39 +00:00
|
|
|
return std::vector<unsigned>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
|
2006-02-21 23:11:00 +00:00
|
|
|
getRegForInlineAsmConstraint(const std::string &Constraint,
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT) const {
|
2006-02-22 00:56:39 +00:00
|
|
|
if (Constraint[0] != '{')
|
|
|
|
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
2006-02-01 01:29:47 +00:00
|
|
|
assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
|
|
|
|
|
|
|
|
// Remove the braces from around the name.
|
|
|
|
std::string RegName(Constraint.begin()+1, Constraint.end()-1);
|
2006-02-22 00:56:39 +00:00
|
|
|
|
|
|
|
// Figure out which register class contains this reg.
|
2008-02-10 18:45:23 +00:00
|
|
|
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
|
|
|
for (TargetRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
|
2006-02-22 00:56:39 +00:00
|
|
|
E = RI->regclass_end(); RCI != E; ++RCI) {
|
|
|
|
const TargetRegisterClass *RC = *RCI;
|
2006-02-22 23:00:51 +00:00
|
|
|
|
|
|
|
// If none of the the value types for this register class are valid, we
|
|
|
|
// can't use it. For example, 64-bit reg classes on 32-bit targets.
|
|
|
|
bool isLegal = false;
|
|
|
|
for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (isTypeLegal(*I)) {
|
|
|
|
isLegal = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLegal) continue;
|
|
|
|
|
2006-02-22 00:56:39 +00:00
|
|
|
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
|
|
|
|
I != E; ++I) {
|
2008-02-26 21:11:01 +00:00
|
|
|
if (StringsEqualNoCase(RegName, RI->get(*I).AsmName))
|
2006-02-22 00:56:39 +00:00
|
|
|
return std::make_pair(*I, RC);
|
|
|
|
}
|
2006-01-26 20:37:03 +00:00
|
|
|
}
|
2006-02-01 01:29:47 +00:00
|
|
|
|
2006-02-22 00:56:39 +00:00
|
|
|
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
2006-01-26 20:37:03 +00:00
|
|
|
}
|
2006-03-13 23:18:16 +00:00
|
|
|
|
2008-04-27 00:09:47 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Constraint Selection.
|
|
|
|
|
2008-10-17 16:47:46 +00:00
|
|
|
/// isMatchingInputConstraint - Return true of this is an input operand that is
|
|
|
|
/// a matching constraint like "4".
|
|
|
|
bool TargetLowering::AsmOperandInfo::isMatchingInputConstraint() const {
|
2008-10-17 16:21:11 +00:00
|
|
|
assert(!ConstraintCode.empty() && "No known constraint!");
|
|
|
|
return isdigit(ConstraintCode[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getMatchedOperand - If this is an input matching constraint, this method
|
|
|
|
/// returns the output operand it matches.
|
|
|
|
unsigned TargetLowering::AsmOperandInfo::getMatchedOperand() const {
|
|
|
|
assert(!ConstraintCode.empty() && "No known constraint!");
|
|
|
|
return atoi(ConstraintCode.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-27 00:09:47 +00:00
|
|
|
/// getConstraintGenerality - Return an integer indicating how general CT
|
|
|
|
/// is.
|
|
|
|
static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
|
|
|
|
switch (CT) {
|
|
|
|
default: assert(0 && "Unknown constraint type!");
|
|
|
|
case TargetLowering::C_Other:
|
|
|
|
case TargetLowering::C_Unknown:
|
|
|
|
return 0;
|
|
|
|
case TargetLowering::C_Register:
|
|
|
|
return 1;
|
|
|
|
case TargetLowering::C_RegisterClass:
|
|
|
|
return 2;
|
|
|
|
case TargetLowering::C_Memory:
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ChooseConstraint - If there are multiple different constraints that we
|
|
|
|
/// could pick for this operand (e.g. "imr") try to pick the 'best' one.
|
2008-04-27 01:49:46 +00:00
|
|
|
/// This is somewhat tricky: constraints fall into four classes:
|
2008-04-27 00:09:47 +00:00
|
|
|
/// Other -> immediates and magic values
|
|
|
|
/// Register -> one specific register
|
|
|
|
/// RegisterClass -> a group of regs
|
|
|
|
/// Memory -> memory
|
|
|
|
/// Ideally, we would pick the most specific constraint possible: if we have
|
|
|
|
/// something that fits into a register, we would pick it. The problem here
|
|
|
|
/// is that if we have something that could either be in a register or in
|
|
|
|
/// memory that use of the register could cause selection of *other*
|
|
|
|
/// operands to fail: they might only succeed if we pick memory. Because of
|
|
|
|
/// this the heuristic we use is:
|
|
|
|
///
|
|
|
|
/// 1) If there is an 'other' constraint, and if the operand is valid for
|
|
|
|
/// that constraint, use it. This makes us take advantage of 'i'
|
|
|
|
/// constraints when available.
|
|
|
|
/// 2) Otherwise, pick the most general constraint present. This prefers
|
|
|
|
/// 'm' over 'r', for example.
|
|
|
|
///
|
|
|
|
static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
|
2008-09-24 00:05:32 +00:00
|
|
|
bool hasMemory, const TargetLowering &TLI,
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Op, SelectionDAG *DAG) {
|
2008-04-27 00:09:47 +00:00
|
|
|
assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
|
|
|
|
unsigned BestIdx = 0;
|
|
|
|
TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown;
|
|
|
|
int BestGenerality = -1;
|
|
|
|
|
|
|
|
// Loop over the options, keeping track of the most general one.
|
|
|
|
for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) {
|
|
|
|
TargetLowering::ConstraintType CType =
|
|
|
|
TLI.getConstraintType(OpInfo.Codes[i]);
|
|
|
|
|
2008-04-27 00:37:18 +00:00
|
|
|
// If this is an 'other' constraint, see if the operand is valid for it.
|
|
|
|
// For example, on X86 we might have an 'rI' constraint. If the operand
|
|
|
|
// is an integer in the range [0..31] we want to use I (saving a load
|
|
|
|
// of a register), otherwise we must use 'r'.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (CType == TargetLowering::C_Other && Op.getNode()) {
|
2008-04-27 00:37:18 +00:00
|
|
|
assert(OpInfo.Codes[i].size() == 1 &&
|
|
|
|
"Unhandled multi-letter 'other' constraint");
|
2008-07-27 21:46:04 +00:00
|
|
|
std::vector<SDValue> ResultOps;
|
2008-09-24 00:05:32 +00:00
|
|
|
TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0], hasMemory,
|
2008-04-27 00:37:18 +00:00
|
|
|
ResultOps, *DAG);
|
|
|
|
if (!ResultOps.empty()) {
|
|
|
|
BestType = CType;
|
|
|
|
BestIdx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-27 00:09:47 +00:00
|
|
|
// This constraint letter is more general than the previous one, use it.
|
|
|
|
int Generality = getConstraintGenerality(CType);
|
|
|
|
if (Generality > BestGenerality) {
|
|
|
|
BestType = CType;
|
|
|
|
BestIdx = i;
|
|
|
|
BestGenerality = Generality;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OpInfo.ConstraintCode = OpInfo.Codes[BestIdx];
|
|
|
|
OpInfo.ConstraintType = BestType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ComputeConstraintToUse - Determines the constraint code and constraint
|
|
|
|
/// type to use for the specific AsmOperandInfo, setting
|
|
|
|
/// OpInfo.ConstraintCode and OpInfo.ConstraintType.
|
2008-04-27 00:37:18 +00:00
|
|
|
void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo,
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Op,
|
2008-09-24 00:05:32 +00:00
|
|
|
bool hasMemory,
|
2008-04-27 00:37:18 +00:00
|
|
|
SelectionDAG *DAG) const {
|
2008-04-27 00:09:47 +00:00
|
|
|
assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
|
|
|
|
|
|
|
|
// Single-letter constraints ('r') are very common.
|
|
|
|
if (OpInfo.Codes.size() == 1) {
|
|
|
|
OpInfo.ConstraintCode = OpInfo.Codes[0];
|
|
|
|
OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
|
|
|
|
} else {
|
2008-09-24 00:05:32 +00:00
|
|
|
ChooseConstraint(OpInfo, hasMemory, *this, Op, DAG);
|
2008-04-27 00:09:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 'X' matches anything.
|
|
|
|
if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
|
|
|
|
// Labels and constants are handled elsewhere ('X' is the only thing
|
|
|
|
// that matches labels).
|
|
|
|
if (isa<BasicBlock>(OpInfo.CallOperandVal) ||
|
|
|
|
isa<ConstantInt>(OpInfo.CallOperandVal))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Otherwise, try to resolve it to something we know about by looking at
|
|
|
|
// the actual operand type.
|
|
|
|
if (const char *Repl = LowerXConstraint(OpInfo.ConstraintVT)) {
|
|
|
|
OpInfo.ConstraintCode = Repl;
|
|
|
|
OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-13 23:18:16 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loop Strength Reduction hooks
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-03-30 23:14:50 +00:00
|
|
|
/// isLegalAddressingMode - Return true if the addressing mode represented
|
|
|
|
/// by AM is legal for this target, for a load/store of the specified type.
|
|
|
|
bool TargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
|
|
|
const Type *Ty) const {
|
|
|
|
// The default implementation of this implements a conservative RISCy, r+r and
|
|
|
|
// r+i addr mode.
|
|
|
|
|
|
|
|
// Allows a sign-extended 16-bit immediate field.
|
|
|
|
if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No global is ever allowed as a base.
|
|
|
|
if (AM.BaseGV)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only support r+r,
|
|
|
|
switch (AM.Scale) {
|
|
|
|
case 0: // "r+i" or just "i", depending on HasBaseReg.
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed.
|
|
|
|
return false;
|
|
|
|
// Otherwise we have r+r or r+i.
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed.
|
|
|
|
return false;
|
|
|
|
// Allow 2*r as r+r.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-11-30 06:02:26 +00:00
|
|
|
struct mu {
|
|
|
|
APInt m; // magic number
|
|
|
|
bool a; // add indicator
|
2008-11-30 06:35:39 +00:00
|
|
|
unsigned s; // shift amount
|
2008-11-30 06:02:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// magicu - calculate the magic numbers required to codegen an integer udiv as
|
|
|
|
/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
|
|
|
|
static mu magicu(const APInt& d) {
|
|
|
|
unsigned p;
|
|
|
|
APInt nc, delta, q1, r1, q2, r2;
|
|
|
|
struct mu magu;
|
|
|
|
magu.a = 0; // initialize "add" indicator
|
|
|
|
APInt allOnes = APInt::getAllOnesValue(d.getBitWidth());
|
|
|
|
APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
|
|
|
|
APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
|
|
|
|
|
|
|
|
nc = allOnes - (-d).urem(d);
|
|
|
|
p = d.getBitWidth() - 1; // initialize p
|
|
|
|
q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc
|
|
|
|
r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc)
|
|
|
|
q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d
|
|
|
|
r2 = signedMax - q2*d; // initialize r2 = rem((2p-1),d)
|
|
|
|
do {
|
|
|
|
p = p + 1;
|
|
|
|
if (r1.uge(nc - r1)) {
|
|
|
|
q1 = q1 + q1 + 1; // update q1
|
|
|
|
r1 = r1 + r1 - nc; // update r1
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
q1 = q1+q1; // update q1
|
|
|
|
r1 = r1+r1; // update r1
|
|
|
|
}
|
|
|
|
if ((r2 + 1).uge(d - r2)) {
|
|
|
|
if (q2.uge(signedMax)) magu.a = 1;
|
|
|
|
q2 = q2+q2 + 1; // update q2
|
|
|
|
r2 = r2+r2 + 1 - d; // update r2
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (q2.uge(signedMin)) magu.a = 1;
|
|
|
|
q2 = q2+q2; // update q2
|
|
|
|
r2 = r2+r2 + 1; // update r2
|
|
|
|
}
|
|
|
|
delta = d - 1 - r2;
|
|
|
|
} while (p < d.getBitWidth()*2 &&
|
|
|
|
(q1.ult(delta) || (q1 == delta && r1 == 0)));
|
|
|
|
magu.m = q2 + 1; // resulting magic number
|
|
|
|
magu.s = p - d.getBitWidth(); // resulting shift
|
|
|
|
return magu;
|
|
|
|
}
|
2006-05-16 17:42:15 +00:00
|
|
|
|
2008-11-30 06:02:26 +00:00
|
|
|
// Magic for divide replacement
|
2006-05-16 17:42:15 +00:00
|
|
|
struct ms {
|
2008-11-30 06:35:39 +00:00
|
|
|
APInt m; // magic number
|
|
|
|
unsigned s; // shift amount
|
2006-05-16 17:42:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
|
|
|
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
|
|
|
/// or -1.
|
2008-11-30 06:35:39 +00:00
|
|
|
static ms magic(const APInt& d) {
|
|
|
|
unsigned p;
|
|
|
|
APInt ad, anc, delta, q1, r1, q2, r2, t;
|
|
|
|
APInt allOnes = APInt::getAllOnesValue(d.getBitWidth());
|
|
|
|
APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
|
|
|
|
APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
|
2006-05-16 17:42:15 +00:00
|
|
|
struct ms mag;
|
|
|
|
|
2008-11-30 06:35:39 +00:00
|
|
|
ad = d.abs();
|
|
|
|
t = signedMin + (d.lshr(d.getBitWidth() - 1));
|
|
|
|
anc = t - 1 - t.urem(ad); // absolute value of nc
|
|
|
|
p = d.getBitWidth() - 1; // initialize p
|
|
|
|
q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc)
|
|
|
|
r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
|
|
|
q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d)
|
|
|
|
r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d))
|
2006-05-16 17:42:15 +00:00
|
|
|
do {
|
|
|
|
p = p + 1;
|
2008-11-30 06:35:39 +00:00
|
|
|
q1 = q1<<1; // update q1 = 2p/abs(nc)
|
|
|
|
r1 = r1<<1; // update r1 = rem(2p/abs(nc))
|
|
|
|
if (r1.uge(anc)) { // must be unsigned comparison
|
2006-05-16 17:42:15 +00:00
|
|
|
q1 = q1 + 1;
|
|
|
|
r1 = r1 - anc;
|
|
|
|
}
|
2008-11-30 06:35:39 +00:00
|
|
|
q2 = q2<<1; // update q2 = 2p/abs(d)
|
|
|
|
r2 = r2<<1; // update r2 = rem(2p/abs(d))
|
|
|
|
if (r2.uge(ad)) { // must be unsigned comparison
|
2006-05-16 17:42:15 +00:00
|
|
|
q2 = q2 + 1;
|
|
|
|
r2 = r2 - ad;
|
|
|
|
}
|
|
|
|
delta = ad - r2;
|
2008-11-30 06:35:39 +00:00
|
|
|
} while (q1.ule(delta) || (q1 == delta && r1 == 0));
|
2006-05-16 17:42:15 +00:00
|
|
|
|
|
|
|
mag.m = q2 + 1;
|
2008-11-30 06:35:39 +00:00
|
|
|
if (d.isNegative()) mag.m = -mag.m; // resulting magic number
|
|
|
|
mag.s = p - d.getBitWidth(); // resulting shift
|
2006-05-16 17:42:15 +00:00
|
|
|
return mag;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant,
|
|
|
|
/// return a DAG expression to select that will generate the same value by
|
|
|
|
/// multiplying by a magic number. See:
|
|
|
|
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
|
|
|
|
std::vector<SDNode*>* Created) const {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = N->getValueType(0);
|
2006-05-16 17:42:15 +00:00
|
|
|
|
|
|
|
// Check to see if we can do this.
|
2008-11-30 06:35:39 +00:00
|
|
|
// FIXME: We should be more aggressive here.
|
|
|
|
if (!isTypeLegal(VT))
|
|
|
|
return SDValue();
|
2006-05-16 17:42:15 +00:00
|
|
|
|
2008-11-30 06:35:39 +00:00
|
|
|
APInt d = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
|
|
|
|
ms magics = magic(d);
|
2006-05-16 17:42:15 +00:00
|
|
|
|
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
2008-11-30 06:35:39 +00:00
|
|
|
// FIXME: We should support doing a MUL in a wider type
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Q;
|
2007-10-08 18:33:35 +00:00
|
|
|
if (isOperationLegal(ISD::MULHS, VT))
|
|
|
|
Q = DAG.getNode(ISD::MULHS, VT, N->getOperand(0),
|
|
|
|
DAG.getConstant(magics.m, VT));
|
|
|
|
else if (isOperationLegal(ISD::SMUL_LOHI, VT))
|
2008-07-27 21:46:04 +00:00
|
|
|
Q = SDValue(DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(VT, VT),
|
2007-10-08 18:33:35 +00:00
|
|
|
N->getOperand(0),
|
2008-08-28 21:40:38 +00:00
|
|
|
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
2007-10-08 18:33:35 +00:00
|
|
|
else
|
2008-07-27 21:46:04 +00:00
|
|
|
return SDValue(); // No mulhs or equvialent
|
2006-05-16 17:42:15 +00:00
|
|
|
// If d > 0 and m < 0, add the numerator
|
2008-11-30 06:35:39 +00:00
|
|
|
if (d.isStrictlyPositive() && magics.m.isNegative()) {
|
2006-05-16 17:42:15 +00:00
|
|
|
Q = DAG.getNode(ISD::ADD, VT, Q, N->getOperand(0));
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
}
|
|
|
|
// If d < 0 and m > 0, subtract the numerator.
|
2008-11-30 06:35:39 +00:00
|
|
|
if (d.isNegative() && magics.m.isStrictlyPositive()) {
|
2006-05-16 17:42:15 +00:00
|
|
|
Q = DAG.getNode(ISD::SUB, VT, Q, N->getOperand(0));
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
}
|
|
|
|
// Shift right algebraic if shift value is nonzero
|
|
|
|
if (magics.s > 0) {
|
|
|
|
Q = DAG.getNode(ISD::SRA, VT, Q,
|
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy()));
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
}
|
|
|
|
// Extract the sign bit and add it to the quotient
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue T =
|
2008-06-06 12:08:01 +00:00
|
|
|
DAG.getNode(ISD::SRL, VT, Q, DAG.getConstant(VT.getSizeInBits()-1,
|
2006-05-16 17:42:15 +00:00
|
|
|
getShiftAmountTy()));
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(T.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
return DAG.getNode(ISD::ADD, VT, Q, T);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant,
|
|
|
|
/// return a DAG expression to select that will generate the same value by
|
|
|
|
/// multiplying by a magic number. See:
|
|
|
|
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
|
|
|
|
std::vector<SDNode*>* Created) const {
|
2008-06-06 12:08:01 +00:00
|
|
|
MVT VT = N->getValueType(0);
|
2008-11-30 06:02:26 +00:00
|
|
|
|
2006-05-16 17:42:15 +00:00
|
|
|
// Check to see if we can do this.
|
2008-11-30 06:02:26 +00:00
|
|
|
// FIXME: We should be more aggressive here.
|
|
|
|
if (!isTypeLegal(VT))
|
|
|
|
return SDValue();
|
|
|
|
|
|
|
|
// FIXME: We should use a narrower constant when the upper
|
|
|
|
// bits are known to be zero.
|
|
|
|
ConstantSDNode *N1C = cast<ConstantSDNode>(N->getOperand(1));
|
|
|
|
mu magics = magicu(N1C->getAPIntValue());
|
|
|
|
|
2006-05-16 17:42:15 +00:00
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
2008-11-30 06:02:26 +00:00
|
|
|
// FIXME: We should support doing a MUL in a wider type
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Q;
|
2007-10-08 18:33:35 +00:00
|
|
|
if (isOperationLegal(ISD::MULHU, VT))
|
|
|
|
Q = DAG.getNode(ISD::MULHU, VT, N->getOperand(0),
|
|
|
|
DAG.getConstant(magics.m, VT));
|
|
|
|
else if (isOperationLegal(ISD::UMUL_LOHI, VT))
|
2008-07-27 21:46:04 +00:00
|
|
|
Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(VT, VT),
|
2007-10-08 18:33:35 +00:00
|
|
|
N->getOperand(0),
|
2008-08-28 21:40:38 +00:00
|
|
|
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
2007-10-08 18:33:35 +00:00
|
|
|
else
|
2008-07-27 21:46:04 +00:00
|
|
|
return SDValue(); // No mulhu or equvialent
|
2006-05-16 17:42:15 +00:00
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
|
|
|
|
if (magics.a == 0) {
|
2008-11-30 06:02:26 +00:00
|
|
|
assert(magics.s < N1C->getAPIntValue().getBitWidth() &&
|
|
|
|
"We shouldn't generate an undefined shift!");
|
2006-05-16 17:42:15 +00:00
|
|
|
return DAG.getNode(ISD::SRL, VT, Q,
|
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy()));
|
|
|
|
} else {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue NPQ = DAG.getNode(ISD::SUB, VT, N->getOperand(0), Q);
|
2006-05-16 17:42:15 +00:00
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(NPQ.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
NPQ = DAG.getNode(ISD::SRL, VT, NPQ,
|
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(NPQ.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
NPQ = DAG.getNode(ISD::ADD, VT, NPQ, Q);
|
|
|
|
if (Created)
|
2008-08-28 21:40:38 +00:00
|
|
|
Created->push_back(NPQ.getNode());
|
2006-05-16 17:42:15 +00:00
|
|
|
return DAG.getNode(ISD::SRL, VT, NPQ,
|
|
|
|
DAG.getConstant(magics.s-1, getShiftAmountTy()));
|
|
|
|
}
|
|
|
|
}
|