2005-01-07 15:44:53 +08:00
|
|
|
//===-- TargetLowering.cpp - Implement the TargetLowering class -----------===//
|
2005-04-22 06:55:34 +08:00
|
|
|
//
|
2005-01-07 15:44:53 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 06:55:34 +08:00
|
|
|
//
|
2005-01-07 15:44:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This implements the TargetLowering class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Target/TargetLowering.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2010-07-10 17:00:22 +08:00
|
|
|
#include "llvm/CodeGen/Analysis.h"
|
2008-05-13 03:56:52 +08:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2010-01-26 14:28:43 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
2005-01-07 15:44:53 +08:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
2011-06-01 20:51:46 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-12 04:10:48 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2006-01-30 12:09:27 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
2010-12-20 04:43:38 +08:00
|
|
|
#include <cctype>
|
2005-01-07 15:44:53 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2007-01-12 10:11:51 +08:00
|
|
|
/// InitLibcallNames - Set default libcall names.
|
|
|
|
///
|
2007-01-13 06:51:10 +08:00
|
|
|
static void InitLibcallNames(const char **Names) {
|
2009-05-03 21:14:08 +08:00
|
|
|
Names[RTLIB::SHL_I16] = "__ashlhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SHL_I32] = "__ashlsi3";
|
|
|
|
Names[RTLIB::SHL_I64] = "__ashldi3";
|
2008-07-12 00:52:29 +08:00
|
|
|
Names[RTLIB::SHL_I128] = "__ashlti3";
|
2009-05-03 21:14:08 +08:00
|
|
|
Names[RTLIB::SRL_I16] = "__lshrhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SRL_I32] = "__lshrsi3";
|
|
|
|
Names[RTLIB::SRL_I64] = "__lshrdi3";
|
2008-07-12 00:52:29 +08:00
|
|
|
Names[RTLIB::SRL_I128] = "__lshrti3";
|
2009-05-03 21:14:08 +08:00
|
|
|
Names[RTLIB::SRA_I16] = "__ashrhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SRA_I32] = "__ashrsi3";
|
|
|
|
Names[RTLIB::SRA_I64] = "__ashrdi3";
|
2008-07-12 00:52:29 +08:00
|
|
|
Names[RTLIB::SRA_I128] = "__ashrti3";
|
2009-11-08 01:14:39 +08:00
|
|
|
Names[RTLIB::MUL_I8] = "__mulqi3";
|
2009-05-03 21:14:08 +08:00
|
|
|
Names[RTLIB::MUL_I16] = "__mulhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::MUL_I32] = "__mulsi3";
|
|
|
|
Names[RTLIB::MUL_I64] = "__muldi3";
|
2008-07-10 23:35:05 +08:00
|
|
|
Names[RTLIB::MUL_I128] = "__multi3";
|
2011-06-18 04:41:29 +08:00
|
|
|
Names[RTLIB::MULO_I32] = "__mulosi4";
|
|
|
|
Names[RTLIB::MULO_I64] = "__mulodi4";
|
|
|
|
Names[RTLIB::MULO_I128] = "__muloti4";
|
2009-11-08 01:14:39 +08:00
|
|
|
Names[RTLIB::SDIV_I8] = "__divqi3";
|
2009-05-03 21:18:16 +08:00
|
|
|
Names[RTLIB::SDIV_I16] = "__divhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SDIV_I32] = "__divsi3";
|
|
|
|
Names[RTLIB::SDIV_I64] = "__divdi3";
|
2008-07-10 23:35:05 +08:00
|
|
|
Names[RTLIB::SDIV_I128] = "__divti3";
|
2009-11-08 01:14:39 +08:00
|
|
|
Names[RTLIB::UDIV_I8] = "__udivqi3";
|
2009-05-09 02:50:54 +08:00
|
|
|
Names[RTLIB::UDIV_I16] = "__udivhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::UDIV_I32] = "__udivsi3";
|
|
|
|
Names[RTLIB::UDIV_I64] = "__udivdi3";
|
2008-07-10 23:35:05 +08:00
|
|
|
Names[RTLIB::UDIV_I128] = "__udivti3";
|
2009-11-08 01:14:39 +08:00
|
|
|
Names[RTLIB::SREM_I8] = "__modqi3";
|
2009-05-03 21:18:16 +08:00
|
|
|
Names[RTLIB::SREM_I16] = "__modhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SREM_I32] = "__modsi3";
|
|
|
|
Names[RTLIB::SREM_I64] = "__moddi3";
|
2008-07-10 23:35:05 +08:00
|
|
|
Names[RTLIB::SREM_I128] = "__modti3";
|
2009-11-08 01:14:39 +08:00
|
|
|
Names[RTLIB::UREM_I8] = "__umodqi3";
|
2009-05-03 21:19:57 +08:00
|
|
|
Names[RTLIB::UREM_I16] = "__umodhi3";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::UREM_I32] = "__umodsi3";
|
|
|
|
Names[RTLIB::UREM_I64] = "__umoddi3";
|
2008-07-10 23:35:05 +08:00
|
|
|
Names[RTLIB::UREM_I128] = "__umodti3";
|
2011-04-01 08:42:02 +08:00
|
|
|
|
|
|
|
// These are generally not available.
|
|
|
|
Names[RTLIB::SDIVREM_I8] = 0;
|
|
|
|
Names[RTLIB::SDIVREM_I16] = 0;
|
|
|
|
Names[RTLIB::SDIVREM_I32] = 0;
|
|
|
|
Names[RTLIB::SDIVREM_I64] = 0;
|
|
|
|
Names[RTLIB::SDIVREM_I128] = 0;
|
|
|
|
Names[RTLIB::UDIVREM_I8] = 0;
|
|
|
|
Names[RTLIB::UDIVREM_I16] = 0;
|
|
|
|
Names[RTLIB::UDIVREM_I32] = 0;
|
|
|
|
Names[RTLIB::UDIVREM_I64] = 0;
|
|
|
|
Names[RTLIB::UDIVREM_I128] = 0;
|
|
|
|
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::NEG_I32] = "__negsi2";
|
|
|
|
Names[RTLIB::NEG_I64] = "__negdi2";
|
|
|
|
Names[RTLIB::ADD_F32] = "__addsf3";
|
|
|
|
Names[RTLIB::ADD_F64] = "__adddf3";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::ADD_F80] = "__addxf3";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::ADD_PPCF128] = "__gcc_qadd";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SUB_F32] = "__subsf3";
|
|
|
|
Names[RTLIB::SUB_F64] = "__subdf3";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::SUB_F80] = "__subxf3";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::SUB_PPCF128] = "__gcc_qsub";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::MUL_F32] = "__mulsf3";
|
|
|
|
Names[RTLIB::MUL_F64] = "__muldf3";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::MUL_F80] = "__mulxf3";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::MUL_PPCF128] = "__gcc_qmul";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::DIV_F32] = "__divsf3";
|
|
|
|
Names[RTLIB::DIV_F64] = "__divdf3";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::DIV_F80] = "__divxf3";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::DIV_PPCF128] = "__gcc_qdiv";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::REM_F32] = "fmodf";
|
|
|
|
Names[RTLIB::REM_F64] = "fmod";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::REM_F80] = "fmodl";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::REM_PPCF128] = "fmodl";
|
2011-07-09 05:39:21 +08:00
|
|
|
Names[RTLIB::FMA_F32] = "fmaf";
|
|
|
|
Names[RTLIB::FMA_F64] = "fma";
|
|
|
|
Names[RTLIB::FMA_F80] = "fmal";
|
|
|
|
Names[RTLIB::FMA_PPCF128] = "fmal";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::POWI_F32] = "__powisf2";
|
|
|
|
Names[RTLIB::POWI_F64] = "__powidf2";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::POWI_F80] = "__powixf2";
|
|
|
|
Names[RTLIB::POWI_PPCF128] = "__powitf2";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SQRT_F32] = "sqrtf";
|
|
|
|
Names[RTLIB::SQRT_F64] = "sqrt";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::SQRT_F80] = "sqrtl";
|
|
|
|
Names[RTLIB::SQRT_PPCF128] = "sqrtl";
|
2008-09-04 08:47:13 +08: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 10:11:51 +08:00
|
|
|
Names[RTLIB::SIN_F32] = "sinf";
|
|
|
|
Names[RTLIB::SIN_F64] = "sin";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::SIN_F80] = "sinl";
|
|
|
|
Names[RTLIB::SIN_PPCF128] = "sinl";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::COS_F32] = "cosf";
|
|
|
|
Names[RTLIB::COS_F64] = "cos";
|
2008-01-10 18:28:30 +08:00
|
|
|
Names[RTLIB::COS_F80] = "cosl";
|
|
|
|
Names[RTLIB::COS_PPCF128] = "cosl";
|
2007-10-12 07:09:10 +08:00
|
|
|
Names[RTLIB::POW_F32] = "powf";
|
|
|
|
Names[RTLIB::POW_F64] = "pow";
|
|
|
|
Names[RTLIB::POW_F80] = "powl";
|
|
|
|
Names[RTLIB::POW_PPCF128] = "powl";
|
2008-08-22 02:38:14 +08: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";
|
2010-03-15 05:08:40 +08:00
|
|
|
Names[RTLIB::COPYSIGN_F32] = "copysignf";
|
|
|
|
Names[RTLIB::COPYSIGN_F64] = "copysign";
|
|
|
|
Names[RTLIB::COPYSIGN_F80] = "copysignl";
|
|
|
|
Names[RTLIB::COPYSIGN_PPCF128] = "copysignl";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2";
|
2010-03-15 02:42:24 +08:00
|
|
|
Names[RTLIB::FPEXT_F16_F32] = "__gnu_h2f_ieee";
|
|
|
|
Names[RTLIB::FPROUND_F32_F16] = "__gnu_f2h_ieee";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2";
|
2008-08-08 03:01:24 +08: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";
|
2010-03-27 05:32:14 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F32_I8] = "__fixsfqi";
|
|
|
|
Names[RTLIB::FPTOSINT_F32_I16] = "__fixsfhi";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti";
|
2010-03-27 05:32:14 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F64_I8] = "__fixdfqi";
|
|
|
|
Names[RTLIB::FPTOSINT_F64_I16] = "__fixdfhi";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F64_I32] = "__fixdfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F64_I64] = "__fixdfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F64_I128] = "__fixdfti";
|
2008-07-10 23:33:02 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I32] = "__fixxfsi";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I64] = "__fixxfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOSINT_F80_I128] = "__fixxfti";
|
2008-06-26 04:24:48 +08:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti";
|
2010-03-27 05:32:14 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F32_I8] = "__fixunssfqi";
|
|
|
|
Names[RTLIB::FPTOUINT_F32_I16] = "__fixunssfhi";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F32_I128] = "__fixunssfti";
|
2010-03-27 05:32:14 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F64_I8] = "__fixunsdfqi";
|
|
|
|
Names[RTLIB::FPTOUINT_F64_I16] = "__fixunsdfhi";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F64_I32] = "__fixunsdfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F64_I64] = "__fixunsdfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F64_I128] = "__fixunsdfti";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F80_I32] = "__fixunsxfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F80_I64] = "__fixunsxfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOUINT_F80_I128] = "__fixunsxfti";
|
2008-06-26 04:24:48 +08:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I32] = "__fixunstfsi";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I64] = "__fixunstfdi";
|
2008-03-11 07:03:31 +08:00
|
|
|
Names[RTLIB::FPTOUINT_PPCF128_I128] = "__fixunstfti";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf";
|
2008-07-12 00:57:02 +08:00
|
|
|
Names[RTLIB::SINTTOFP_I32_F80] = "__floatsixf";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_PPCF128] = "__floatsitf";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf";
|
2007-10-06 04:04:43 +08:00
|
|
|
Names[RTLIB::SINTTOFP_I64_F80] = "__floatdixf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_PPCF128] = "__floatditf";
|
2008-03-05 09:08:17 +08: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 10:11:51 +08:00
|
|
|
Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf";
|
2008-07-12 01:00:14 +08:00
|
|
|
Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf";
|
2007-01-12 10:11:51 +08:00
|
|
|
Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf";
|
2008-07-12 01:00:14 +08: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 10:11:51 +08: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 17:29:11 +08:00
|
|
|
Names[RTLIB::O_F32] = "__unordsf2";
|
|
|
|
Names[RTLIB::O_F64] = "__unorddf2";
|
2009-07-30 17:12:56 +08:00
|
|
|
Names[RTLIB::MEMCPY] = "memcpy";
|
|
|
|
Names[RTLIB::MEMMOVE] = "memmove";
|
|
|
|
Names[RTLIB::MEMSET] = "memset";
|
2009-05-23 04:36:31 +08:00
|
|
|
Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume";
|
2010-06-19 05:43:38 +08:00
|
|
|
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1] = "__sync_val_compare_and_swap_1";
|
|
|
|
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2] = "__sync_val_compare_and_swap_2";
|
|
|
|
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_4] = "__sync_val_compare_and_swap_4";
|
|
|
|
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_8] = "__sync_val_compare_and_swap_8";
|
2010-06-19 07:03:10 +08:00
|
|
|
Names[RTLIB::SYNC_LOCK_TEST_AND_SET_1] = "__sync_lock_test_and_set_1";
|
|
|
|
Names[RTLIB::SYNC_LOCK_TEST_AND_SET_2] = "__sync_lock_test_and_set_2";
|
|
|
|
Names[RTLIB::SYNC_LOCK_TEST_AND_SET_4] = "__sync_lock_test_and_set_4";
|
|
|
|
Names[RTLIB::SYNC_LOCK_TEST_AND_SET_8] = "__sync_lock_test_and_set_8";
|
2010-06-19 05:43:38 +08:00
|
|
|
Names[RTLIB::SYNC_FETCH_AND_ADD_1] = "__sync_fetch_and_add_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_ADD_2] = "__sync_fetch_and_add_2";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_ADD_4] = "__sync_fetch_and_add_4";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_ADD_8] = "__sync_fetch_and_add_8";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_SUB_1] = "__sync_fetch_and_sub_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_SUB_2] = "__sync_fetch_and_sub_2";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_SUB_4] = "__sync_fetch_and_sub_4";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_SUB_8] = "__sync_fetch_and_sub_8";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_AND_1] = "__sync_fetch_and_and_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_AND_2] = "__sync_fetch_and_and_2";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_AND_4] = "__sync_fetch_and_and_4";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_AND_8] = "__sync_fetch_and_and_8";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_OR_1] = "__sync_fetch_and_or_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_OR_2] = "__sync_fetch_and_or_2";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_OR_4] = "__sync_fetch_and_or_4";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_OR_8] = "__sync_fetch_and_or_8";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_XOR_1] = "__sync_fetch_and_xor_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_XOR_2] = "__sync_fetch_and_xor_2";
|
2011-10-14 23:53:48 +08:00
|
|
|
Names[RTLIB::SYNC_FETCH_AND_XOR_4] = "__sync_fetch_and_xor_4";
|
2010-06-19 05:43:38 +08:00
|
|
|
Names[RTLIB::SYNC_FETCH_AND_XOR_8] = "__sync_fetch_and_xor_8";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_NAND_1] = "__sync_fetch_and_nand_1";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_NAND_2] = "__sync_fetch_and_nand_2";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_NAND_4] = "__sync_fetch_and_nand_4";
|
|
|
|
Names[RTLIB::SYNC_FETCH_AND_NAND_8] = "__sync_fetch_and_nand_8";
|
2007-01-31 17:29:11 +08:00
|
|
|
}
|
|
|
|
|
2009-08-15 04:10:52 +08:00
|
|
|
/// InitLibcallCallingConvs - Set default libcall CallingConvs.
|
|
|
|
///
|
|
|
|
static void InitLibcallCallingConvs(CallingConv::ID *CCs) {
|
|
|
|
for (int i = 0; i < RTLIB::UNKNOWN_LIBCALL; ++i) {
|
|
|
|
CCs[i] = CallingConv::C;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-17 10:36:29 +08:00
|
|
|
/// getFPEXT - Return the FPEXT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getFPEXT(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPEXT_F32_F64;
|
|
|
|
}
|
2010-03-15 02:42:24 +08:00
|
|
|
|
2008-07-17 10:36:29 +08:00
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPROUND - Return the FPROUND_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getFPROUND(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::f32) {
|
|
|
|
if (OpVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPROUND_F64_F32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::f80)
|
2008-08-08 03:01:24 +08:00
|
|
|
return FPROUND_F80_F32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::ppcf128)
|
2008-08-08 03:01:24 +08:00
|
|
|
return FPROUND_PPCF128_F32;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (RetVT == MVT::f64) {
|
|
|
|
if (OpVT == MVT::f80)
|
2008-08-08 03:01:24 +08:00
|
|
|
return FPROUND_F80_F64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::ppcf128)
|
2008-08-08 03:01:24 +08:00
|
|
|
return FPROUND_PPCF128_F64;
|
2008-07-17 10:36:29 +08:00
|
|
|
}
|
2010-03-15 02:42:24 +08:00
|
|
|
|
2008-07-17 10:36:29 +08:00
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getFPTOSINT(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::i8)
|
2009-06-16 17:03:58 +08:00
|
|
|
return FPTOSINT_F32_I8;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i16)
|
2009-06-16 17:03:58 +08:00
|
|
|
return FPTOSINT_F32_I16;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F32_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F32_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F32_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::f64) {
|
2010-03-27 05:32:14 +08:00
|
|
|
if (RetVT == MVT::i8)
|
|
|
|
return FPTOSINT_F64_I8;
|
|
|
|
if (RetVT == MVT::i16)
|
|
|
|
return FPTOSINT_F64_I16;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F64_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F64_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F64_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::f80) {
|
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F80_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F80_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_F80_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::ppcf128) {
|
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_PPCF128_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_PPCF128_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOSINT_PPCF128_I128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getFPTOUINT(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::f32) {
|
|
|
|
if (RetVT == MVT::i8)
|
2009-06-16 17:03:58 +08:00
|
|
|
return FPTOUINT_F32_I8;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i16)
|
2009-06-16 17:03:58 +08:00
|
|
|
return FPTOUINT_F32_I16;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F32_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F32_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F32_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::f64) {
|
2010-03-27 05:32:14 +08:00
|
|
|
if (RetVT == MVT::i8)
|
|
|
|
return FPTOUINT_F64_I8;
|
|
|
|
if (RetVT == MVT::i16)
|
|
|
|
return FPTOUINT_F64_I16;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F64_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F64_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F64_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::f80) {
|
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F80_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F80_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_F80_I128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::ppcf128) {
|
|
|
|
if (RetVT == MVT::i32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_PPCF128_I32;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_PPCF128_I64;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (RetVT == MVT::i128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return FPTOUINT_PPCF128_I128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getSINTTOFP(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::i32) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I32_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I32_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I32_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I32_PPCF128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::i64) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I64_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I64_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I64_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I64_PPCF128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::i128) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I128_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I128_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I128_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return SINTTOFP_I128_PPCF128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or
|
|
|
|
/// UNKNOWN_LIBCALL if there is none.
|
2009-08-11 06:56:29 +08:00
|
|
|
RTLIB::Libcall RTLIB::getUINTTOFP(EVT OpVT, EVT RetVT) {
|
2009-08-12 04:47:22 +08:00
|
|
|
if (OpVT == MVT::i32) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I32_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I32_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I32_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I32_PPCF128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::i64) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I64_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I64_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I64_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I64_PPCF128;
|
2009-08-12 04:47:22 +08:00
|
|
|
} else if (OpVT == MVT::i128) {
|
|
|
|
if (RetVT == MVT::f32)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I128_F32;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f64)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I128_F64;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::f80)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I128_F80;
|
2012-12-19 14:39:17 +08:00
|
|
|
if (RetVT == MVT::ppcf128)
|
2008-07-17 10:36:29 +08:00
|
|
|
return UINTTOFP_I128_PPCF128;
|
|
|
|
}
|
|
|
|
return UNKNOWN_LIBCALL;
|
|
|
|
}
|
|
|
|
|
2007-01-31 17:29:11 +08: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 10:11:51 +08:00
|
|
|
}
|
|
|
|
|
2009-07-28 11:13:23 +08:00
|
|
|
/// NOTE: The constructor takes ownership of TLOF.
|
2010-04-21 09:34:56 +08:00
|
|
|
TargetLowering::TargetLowering(const TargetMachine &tm,
|
|
|
|
const TargetLoweringObjectFile *tlof)
|
2012-10-09 00:38:25 +08:00
|
|
|
: TM(tm), TD(TM.getDataLayout()), TLOF(*tlof) {
|
2005-01-16 15:28:11 +08:00
|
|
|
// All operations default to being supported.
|
|
|
|
memset(OpActions, 0, sizeof(OpActions));
|
2008-10-15 05:26:46 +08:00
|
|
|
memset(LoadExtActions, 0, sizeof(LoadExtActions));
|
2008-01-18 03:59:44 +08:00
|
|
|
memset(TruncStoreActions, 0, sizeof(TruncStoreActions));
|
2008-01-19 03:36:20 +08:00
|
|
|
memset(IndexedModeActions, 0, sizeof(IndexedModeActions));
|
2008-10-15 10:05:31 +08:00
|
|
|
memset(CondCodeActions, 0, sizeof(CondCodeActions));
|
2007-07-10 04:49:44 +08:00
|
|
|
|
2007-12-23 04:47:56 +08:00
|
|
|
// Set default actions for various operations.
|
2009-08-12 04:47:22 +08:00
|
|
|
for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) {
|
2007-12-23 04:47:56 +08:00
|
|
|
// Default all indexed load / store to expand.
|
2006-11-10 02:56:43 +08:00
|
|
|
for (unsigned IM = (unsigned)ISD::PRE_INC;
|
|
|
|
IM != (unsigned)ISD::LAST_INDEXED_MODE; ++IM) {
|
2009-08-12 04:47:22 +08:00
|
|
|
setIndexedLoadAction(IM, (MVT::SimpleValueType)VT, Expand);
|
|
|
|
setIndexedStoreAction(IM, (MVT::SimpleValueType)VT, Expand);
|
2006-11-10 02:56:43 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-12-23 04:47:56 +08:00
|
|
|
// These operations default to expand.
|
2009-08-12 04:47:22 +08:00
|
|
|
setOperationAction(ISD::FGETSIGN, (MVT::SimpleValueType)VT, Expand);
|
|
|
|
setOperationAction(ISD::CONCAT_VECTORS, (MVT::SimpleValueType)VT, Expand);
|
2006-11-10 02:56:43 +08:00
|
|
|
}
|
2008-03-11 03:38:10 +08:00
|
|
|
|
|
|
|
// Most targets ignore the @llvm.prefetch intrinsic.
|
2009-08-12 04:47:22 +08:00
|
|
|
setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
// ConstantFP nodes default to expand. Targets can either change this to
|
2009-10-28 03:56:55 +08:00
|
|
|
// Legal, in which case all fp constants are legal, or use isFPImmLegal()
|
2008-02-14 16:57:00 +08:00
|
|
|
// to optimize expansions for certain constants.
|
2011-12-20 08:02:33 +08:00
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f16, Expand);
|
2009-08-12 04:47:22 +08:00
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::ConstantFP, MVT::f80, Expand);
|
2005-01-07 15:44:53 +08:00
|
|
|
|
2008-09-23 05:57:32 +08:00
|
|
|
// These library functions default to expand.
|
2011-12-20 08:02:33 +08:00
|
|
|
setOperationAction(ISD::FLOG , MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FLOG2, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FLOG10, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FEXP , MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FEXP2, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FFLOOR, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FNEARBYINT, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FCEIL, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FRINT, MVT::f16, Expand);
|
|
|
|
setOperationAction(ISD::FTRUNC, MVT::f16, Expand);
|
2011-12-09 03:32:14 +08:00
|
|
|
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);
|
|
|
|
setOperationAction(ISD::FFLOOR, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FNEARBYINT, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FCEIL, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FRINT, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FTRUNC, MVT::f32, Expand);
|
2011-12-20 08:02:33 +08:00
|
|
|
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::FFLOOR, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FNEARBYINT, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FCEIL, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FRINT, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FTRUNC, MVT::f64, Expand);
|
2008-09-23 05:57:32 +08:00
|
|
|
|
2008-01-16 05:58:08 +08:00
|
|
|
// Default ISD::TRAP to expand (which turns it into abort).
|
2009-08-12 04:47:22 +08:00
|
|
|
setOperationAction(ISD::TRAP, MVT::Other, Expand);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2012-10-20 04:11:16 +08:00
|
|
|
// On most systems, DEBUGTRAP and TRAP have no difference. The "Expand"
|
|
|
|
// here is to inform DAG Legalizer to replace DEBUGTRAP with TRAP.
|
|
|
|
//
|
|
|
|
setOperationAction(ISD::DEBUGTRAP, MVT::Other, Expand);
|
|
|
|
|
2006-05-03 09:29:57 +08:00
|
|
|
IsLittleEndian = TD->isLittleEndian();
|
2012-10-10 00:06:12 +08:00
|
|
|
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize(0));
|
2009-08-12 04:47:22 +08:00
|
|
|
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
|
2007-09-07 12:06:50 +08:00
|
|
|
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
|
2006-02-14 16:38:30 +08:00
|
|
|
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
|
2011-01-06 14:52:41 +08:00
|
|
|
maxStoresPerMemsetOptSize = maxStoresPerMemcpyOptSize
|
|
|
|
= maxStoresPerMemmoveOptSize = 4;
|
2009-05-14 05:42:09 +08:00
|
|
|
benefitFromCodePlacementOpt = false;
|
2006-12-11 07:12:42 +08:00
|
|
|
UseUnderscoreSetJmp = false;
|
|
|
|
UseUnderscoreLongJmp = false;
|
2007-02-25 09:28:05 +08:00
|
|
|
SelectIsExpensive = false;
|
2005-10-21 08:02:42 +08:00
|
|
|
IntDivIsCheap = false;
|
|
|
|
Pow2DivIsCheap = false;
|
2010-12-01 02:12:52 +08:00
|
|
|
JumpIsExpensive = false;
|
2012-05-05 20:49:14 +08:00
|
|
|
predictableSelectIsExpensive = false;
|
2006-01-26 02:57:15 +08:00
|
|
|
StackPointerRegisterToSaveRestore = 0;
|
2007-02-23 02:04:49 +08:00
|
|
|
ExceptionPointerRegister = 0;
|
|
|
|
ExceptionSelectorRegister = 0;
|
2008-11-23 23:47:28 +08:00
|
|
|
BooleanContents = UndefinedBooleanContent;
|
2011-09-07 03:07:46 +08:00
|
|
|
BooleanVectorContents = UndefinedBooleanContent;
|
2011-10-25 01:45:02 +08:00
|
|
|
SchedPreferenceInfo = Sched::ILP;
|
2006-09-06 01:39:15 +08:00
|
|
|
JumpBufSize = 0;
|
2006-09-04 15:44:11 +08:00
|
|
|
JumpBufAlignment = 0;
|
2011-05-07 04:34:06 +08:00
|
|
|
MinFunctionAlignment = 0;
|
|
|
|
PrefFunctionAlignment = 0;
|
2008-02-28 08:43:03 +08:00
|
|
|
PrefLoopAlignment = 0;
|
2010-07-11 12:01:49 +08:00
|
|
|
MinStackArgumentAlignment = 1;
|
2010-06-24 00:07:42 +08:00
|
|
|
ShouldFoldAtomicFences = false;
|
2011-08-04 05:06:02 +08:00
|
|
|
InsertFencesForAtomic = false;
|
2012-07-03 06:39:56 +08:00
|
|
|
SupportJumpTables = true;
|
2012-09-26 04:35:36 +08:00
|
|
|
MinimumJumpTableEntries = 4;
|
2007-01-12 10:11:51 +08:00
|
|
|
|
|
|
|
InitLibcallNames(LibcallRoutineNames);
|
2007-01-31 17:29:11 +08:00
|
|
|
InitCmpLibcallCCs(CmpLibcallCCs);
|
2009-08-15 04:10:52 +08:00
|
|
|
InitLibcallCallingConvs(LibcallCallingConvs);
|
2005-01-07 15:44:53 +08:00
|
|
|
}
|
|
|
|
|
2009-07-28 11:13:23 +08:00
|
|
|
TargetLowering::~TargetLowering() {
|
|
|
|
delete &TLOF;
|
|
|
|
}
|
2005-01-16 15:28:11 +08:00
|
|
|
|
2011-02-26 05:41:48 +08:00
|
|
|
MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const {
|
2012-10-10 00:06:12 +08:00
|
|
|
return MVT::getIntegerVT(8*TD->getPointerSize(0));
|
2011-02-26 05:41:48 +08:00
|
|
|
}
|
|
|
|
|
2010-02-11 07:37:45 +08:00
|
|
|
/// canOpTrap - Returns true if the operation can trap for the value type.
|
|
|
|
/// VT must be a legal type.
|
|
|
|
bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const {
|
|
|
|
assert(isTypeLegal(VT));
|
|
|
|
switch (Op) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case ISD::FDIV:
|
|
|
|
case ISD::FREM:
|
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::UDIV:
|
|
|
|
case ISD::SREM:
|
|
|
|
case ISD::UREM:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-12 08:36:31 +08:00
|
|
|
static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT,
|
2010-07-05 13:36:21 +08:00
|
|
|
unsigned &NumIntermediates,
|
2012-12-19 19:53:21 +08:00
|
|
|
MVT &RegisterVT,
|
2010-07-05 13:36:21 +08:00
|
|
|
TargetLowering *TLI) {
|
2009-08-12 08:36:31 +08:00
|
|
|
// Figure out the right, legal destination reg to copy into.
|
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
MVT EltTy = VT.getVectorElementType();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-08-12 08:36:31 +08:00
|
|
|
unsigned NumVectorRegs = 1;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
// FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we
|
2009-08-12 08:36:31 +08:00
|
|
|
// could break down into LHS/RHS like LegalizeDAG does.
|
|
|
|
if (!isPowerOf2_32(NumElts)) {
|
|
|
|
NumVectorRegs = NumElts;
|
|
|
|
NumElts = 1;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-08-12 08:36:31 +08: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.
|
|
|
|
while (NumElts > 1 && !TLI->isTypeLegal(MVT::getVectorVT(EltTy, NumElts))) {
|
|
|
|
NumElts >>= 1;
|
|
|
|
NumVectorRegs <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
NumIntermediates = NumVectorRegs;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-08-12 08:36:31 +08:00
|
|
|
MVT NewVT = MVT::getVectorVT(EltTy, NumElts);
|
|
|
|
if (!TLI->isTypeLegal(NewVT))
|
|
|
|
NewVT = EltTy;
|
|
|
|
IntermediateVT = NewVT;
|
|
|
|
|
2011-06-12 22:56:55 +08:00
|
|
|
unsigned NewVTSize = NewVT.getSizeInBits();
|
|
|
|
|
|
|
|
// Convert sizes such as i33 to i64.
|
|
|
|
if (!isPowerOf2_32(NewVTSize))
|
|
|
|
NewVTSize = NextPowerOf2(NewVTSize);
|
|
|
|
|
2012-12-19 19:48:16 +08:00
|
|
|
MVT DestVT = TLI->getRegisterType(NewVT);
|
2009-08-12 08:36:31 +08:00
|
|
|
RegisterVT = DestVT;
|
2010-07-05 13:53:14 +08:00
|
|
|
if (EVT(DestVT).bitsLT(NewVT)) // Value is expanded, e.g. i64 -> i16.
|
2011-06-12 22:56:55 +08:00
|
|
|
return NumVectorRegs*(NewVTSize/DestVT.getSizeInBits());
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-07-05 13:53:14 +08:00
|
|
|
// Otherwise, promotion or legal types use the same number of registers as
|
|
|
|
// the vector decimated to the appropriate level.
|
|
|
|
return NumVectorRegs;
|
2009-08-12 08:36:31 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 02:47:01 +08:00
|
|
|
/// isLegalRC - Return true if the value types that can be represented by the
|
|
|
|
/// specified register class are all legal.
|
|
|
|
bool TargetLowering::isLegalRC(const TargetRegisterClass *RC) const {
|
|
|
|
for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (isTypeLegal(*I))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// findRepresentativeClass - Return the largest legal super-reg register class
|
2010-07-21 14:09:07 +08:00
|
|
|
/// of the register class for the specified type and its associated "cost".
|
|
|
|
std::pair<const TargetRegisterClass*, uint8_t>
|
2012-12-19 19:30:36 +08:00
|
|
|
TargetLowering::findRepresentativeClass(MVT VT) const {
|
2012-05-04 10:19:22 +08:00
|
|
|
const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo();
|
2012-12-19 19:30:36 +08:00
|
|
|
const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy];
|
2010-07-21 14:09:07 +08:00
|
|
|
if (!RC)
|
|
|
|
return std::make_pair(RC, 0);
|
2012-05-04 10:19:22 +08:00
|
|
|
|
|
|
|
// Compute the set of all super-register classes.
|
|
|
|
BitVector SuperRegRC(TRI->getNumRegClasses());
|
2012-05-05 06:53:28 +08:00
|
|
|
for (SuperRegClassIterator RCI(RC, TRI); RCI.isValid(); ++RCI)
|
2012-05-04 10:19:22 +08:00
|
|
|
SuperRegRC.setBitsInMask(RCI.getMask());
|
|
|
|
|
2012-05-05 06:53:28 +08:00
|
|
|
// Find the first legal register class with the largest spill size.
|
|
|
|
const TargetRegisterClass *BestRC = RC;
|
2012-05-04 10:19:22 +08:00
|
|
|
for (int i = SuperRegRC.find_first(); i >= 0; i = SuperRegRC.find_next(i)) {
|
|
|
|
const TargetRegisterClass *SuperRC = TRI->getRegClass(i);
|
2012-05-05 06:53:28 +08:00
|
|
|
// We want the largest possible spill size.
|
|
|
|
if (SuperRC->getSize() <= BestRC->getSize())
|
|
|
|
continue;
|
|
|
|
if (!isLegalRC(SuperRC))
|
|
|
|
continue;
|
|
|
|
BestRC = SuperRC;
|
2010-07-20 02:47:01 +08:00
|
|
|
}
|
2012-05-05 06:53:28 +08:00
|
|
|
return std::make_pair(BestRC, 1);
|
2010-07-20 02:47:01 +08:00
|
|
|
}
|
|
|
|
|
2005-01-07 15:44:53 +08:00
|
|
|
/// computeRegisterProperties - Once all of the register classes are added,
|
|
|
|
/// this allows us to compute derived properties we expose.
|
|
|
|
void TargetLowering::computeRegisterProperties() {
|
2009-08-12 04:47:22 +08:00
|
|
|
assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE &&
|
2005-01-16 09:10:58 +08:00
|
|
|
"Too many value types for ValueTypeActions to hold!");
|
|
|
|
|
2007-06-29 07:29:44 +08:00
|
|
|
// Everything defaults to needing one register.
|
2009-08-12 04:47:22 +08:00
|
|
|
for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) {
|
2007-06-21 22:42:22 +08:00
|
|
|
NumRegistersForVT[i] = 1;
|
2009-08-12 04:47:22 +08:00
|
|
|
RegisterTypeForVT[i] = TransformToType[i] = (MVT::SimpleValueType)i;
|
2007-06-29 07:29:44 +08:00
|
|
|
}
|
|
|
|
// ...except isVoid, which doesn't need any registers.
|
2009-08-12 04:47:22 +08:00
|
|
|
NumRegistersForVT[MVT::isVoid] = 0;
|
2005-04-22 06:55:34 +08:00
|
|
|
|
2005-01-07 15:44:53 +08:00
|
|
|
// Find the largest integer register class.
|
2009-08-12 04:47:22 +08:00
|
|
|
unsigned LargestIntReg = MVT::LAST_INTEGER_VALUETYPE;
|
2005-01-07 15:44:53 +08:00
|
|
|
for (; RegClassForVT[LargestIntReg] == 0; --LargestIntReg)
|
2009-08-12 04:47:22 +08:00
|
|
|
assert(LargestIntReg != MVT::i1 && "No integer registers defined!");
|
2005-01-07 15:44:53 +08:00
|
|
|
|
|
|
|
// Every integer value type larger than this largest register takes twice as
|
|
|
|
// many registers to represent as the previous ValueType.
|
2012-11-23 16:35:04 +08:00
|
|
|
for (unsigned ExpandedReg = LargestIntReg + 1;
|
|
|
|
ExpandedReg <= MVT::LAST_INTEGER_VALUETYPE; ++ExpandedReg) {
|
2007-06-21 22:42:22 +08:00
|
|
|
NumRegistersForVT[ExpandedReg] = 2*NumRegistersForVT[ExpandedReg-1];
|
2009-08-12 04:47:22 +08:00
|
|
|
RegisterTypeForVT[ExpandedReg] = (MVT::SimpleValueType)LargestIntReg;
|
|
|
|
TransformToType[ExpandedReg] = (MVT::SimpleValueType)(ExpandedReg - 1);
|
2012-11-23 16:35:04 +08:00
|
|
|
ValueTypeActions.setTypeAction((MVT::SimpleValueType)ExpandedReg,
|
|
|
|
TypeExpandInteger);
|
2007-06-29 07:29:44 +08:00
|
|
|
}
|
2005-01-07 15:44:53 +08:00
|
|
|
|
2007-06-29 07:29:44 +08:00
|
|
|
// Inspect all of the ValueType's smaller than the largest integer
|
|
|
|
// register to see which ones need promotion.
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned LegalIntReg = LargestIntReg;
|
|
|
|
for (unsigned IntReg = LargestIntReg - 1;
|
2009-08-12 04:47:22 +08:00
|
|
|
IntReg >= (unsigned)MVT::i1; --IntReg) {
|
2012-12-14 04:42:43 +08:00
|
|
|
MVT IVT = (MVT::SimpleValueType)IntReg;
|
2008-06-06 20:08:01 +08:00
|
|
|
if (isTypeLegal(IVT)) {
|
2007-06-29 07:29:44 +08:00
|
|
|
LegalIntReg = IntReg;
|
|
|
|
} else {
|
2008-06-06 20:08:01 +08:00
|
|
|
RegisterTypeForVT[IntReg] = TransformToType[IntReg] =
|
2012-09-06 06:26:57 +08:00
|
|
|
(const MVT::SimpleValueType)LegalIntReg;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(IVT, TypePromoteInteger);
|
2007-06-29 07:29:44 +08:00
|
|
|
}
|
|
|
|
}
|
2005-04-22 06:55:34 +08:00
|
|
|
|
2007-10-06 04:04:43 +08:00
|
|
|
// ppcf128 type is really two f64's.
|
2009-08-12 04:47:22 +08:00
|
|
|
if (!isTypeLegal(MVT::ppcf128)) {
|
|
|
|
NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64];
|
|
|
|
RegisterTypeForVT[MVT::ppcf128] = MVT::f64;
|
|
|
|
TransformToType[MVT::ppcf128] = MVT::f64;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(MVT::ppcf128, TypeExpandFloat);
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
2007-10-06 04:04:43 +08:00
|
|
|
|
2007-06-29 07:29:44 +08: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.
|
2009-08-12 04:47:22 +08:00
|
|
|
if (!isTypeLegal(MVT::f64)) {
|
|
|
|
NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64];
|
|
|
|
RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64];
|
|
|
|
TransformToType[MVT::f64] = MVT::i64;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(MVT::f64, TypeSoftenFloat);
|
2006-12-09 10:42:38 +08:00
|
|
|
}
|
2007-06-29 07:29:44 +08: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.
|
2009-08-12 04:47:22 +08:00
|
|
|
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;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(MVT::f32, TypePromoteInteger);
|
2007-06-29 07:29:44 +08:00
|
|
|
} else {
|
2009-08-12 04:47:22 +08:00
|
|
|
NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32];
|
|
|
|
RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::i32];
|
|
|
|
TransformToType[MVT::f32] = MVT::i32;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(MVT::f32, TypeSoftenFloat);
|
2007-06-29 07:29:44 +08:00
|
|
|
}
|
2006-12-09 10:42:38 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-06-29 07:29:44 +08:00
|
|
|
// Loop over all of the vector value types to see which need transformations.
|
2009-08-12 04:47:22 +08:00
|
|
|
for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE;
|
|
|
|
i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
|
2009-08-12 08:36:31 +08:00
|
|
|
MVT VT = (MVT::SimpleValueType)i;
|
2010-07-05 13:36:21 +08:00
|
|
|
if (isTypeLegal(VT)) continue;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
// Determine if there is a legal wider type. If so, we should promote to
|
|
|
|
// that wider vector type.
|
2012-12-19 19:42:00 +08:00
|
|
|
MVT EltVT = VT.getVectorElementType();
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
unsigned NElts = VT.getVectorNumElements();
|
2012-11-29 22:26:24 +08:00
|
|
|
if (NElts != 1 && !shouldSplitVectorElementType(EltVT)) {
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
bool IsLegalWiderType = false;
|
2011-06-05 04:32:01 +08:00
|
|
|
// First try to promote the elements of integer vectors. If no legal
|
|
|
|
// promotion was found, fallback to the widen-vector method.
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) {
|
2012-12-19 19:42:00 +08:00
|
|
|
MVT SVT = (MVT::SimpleValueType)nVT;
|
2011-06-05 04:32:01 +08:00
|
|
|
// Promote vectors of integers to vectors with the same number
|
|
|
|
// of elements, with a wider element type.
|
|
|
|
if (SVT.getVectorElementType().getSizeInBits() > EltVT.getSizeInBits()
|
|
|
|
&& SVT.getVectorNumElements() == NElts &&
|
|
|
|
isTypeLegal(SVT) && SVT.getScalarType().isInteger()) {
|
|
|
|
TransformToType[i] = SVT;
|
|
|
|
RegisterTypeForVT[i] = SVT;
|
|
|
|
NumRegistersForVT[i] = 1;
|
|
|
|
ValueTypeActions.setTypeAction(VT, TypePromoteInteger);
|
|
|
|
IsLegalWiderType = true;
|
|
|
|
break;
|
2011-06-01 20:51:46 +08:00
|
|
|
}
|
2011-06-05 04:32:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IsLegalWiderType) continue;
|
2011-06-01 20:51:46 +08:00
|
|
|
|
2011-06-05 04:32:01 +08:00
|
|
|
// Try to widen the vector.
|
|
|
|
for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) {
|
2012-12-19 19:42:00 +08:00
|
|
|
MVT SVT = (MVT::SimpleValueType)nVT;
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
if (SVT.getVectorElementType() == EltVT &&
|
2010-11-23 11:31:01 +08:00
|
|
|
SVT.getVectorNumElements() > NElts &&
|
2010-10-21 05:32:10 +08:00
|
|
|
isTypeLegal(SVT)) {
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
TransformToType[i] = SVT;
|
|
|
|
RegisterTypeForVT[i] = SVT;
|
|
|
|
NumRegistersForVT[i] = 1;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(VT, TypeWidenVector);
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
IsLegalWiderType = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsLegalWiderType) continue;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-07-05 13:36:21 +08:00
|
|
|
MVT IntermediateVT;
|
2012-12-19 19:53:21 +08:00
|
|
|
MVT RegisterVT;
|
2010-07-05 13:36:21 +08:00
|
|
|
unsigned NumIntermediates;
|
|
|
|
NumRegistersForVT[i] =
|
|
|
|
getVectorTypeBreakdownMVT(VT, IntermediateVT, NumIntermediates,
|
|
|
|
RegisterVT, this);
|
2012-12-19 19:53:21 +08:00
|
|
|
RegisterTypeForVT[i] = RegisterVT;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2012-12-19 19:42:00 +08:00
|
|
|
MVT NVT = VT.getPow2VectorType();
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
if (NVT == VT) {
|
|
|
|
// Type is already a power of 2. The default action is to split.
|
|
|
|
TransformToType[i] = MVT::Other;
|
2011-05-29 01:57:14 +08:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
ValueTypeActions.setTypeAction(VT,
|
|
|
|
NumElts > 1 ? TypeSplitVector : TypeScalarizeVector);
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
} else {
|
|
|
|
TransformToType[i] = NVT;
|
2011-05-29 01:57:14 +08:00
|
|
|
ValueTypeActions.setTypeAction(VT, TypeWidenVector);
|
2007-06-26 00:23:39 +08:00
|
|
|
}
|
2006-03-17 03:50:01 +08:00
|
|
|
}
|
2010-07-20 02:47:01 +08:00
|
|
|
|
|
|
|
// Determine the 'representative' register class for each value type.
|
|
|
|
// An representative register class is the largest (meaning one which is
|
|
|
|
// not a sub-register class / subreg register class) legal register class for
|
|
|
|
// a group of value types. For example, on i386, i8, i16, and i32
|
|
|
|
// representative would be GR32; while on x86_64 it's GR64.
|
2010-07-20 06:15:08 +08:00
|
|
|
for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) {
|
2010-07-21 14:09:07 +08:00
|
|
|
const TargetRegisterClass* RRC;
|
|
|
|
uint8_t Cost;
|
|
|
|
tie(RRC, Cost) = findRepresentativeClass((MVT::SimpleValueType)i);
|
|
|
|
RepRegClassForVT[i] = RRC;
|
|
|
|
RepRegClassCostForVT[i] = Cost;
|
2010-07-20 06:15:08 +08:00
|
|
|
}
|
2005-01-16 09:10:58 +08:00
|
|
|
}
|
2005-01-16 15:28:11 +08:00
|
|
|
|
2005-12-20 14:22:03 +08:00
|
|
|
const char *TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-12-22 07:05:39 +08:00
|
|
|
|
2011-09-07 03:07:46 +08:00
|
|
|
EVT TargetLowering::getSetCCResultType(EVT VT) const {
|
|
|
|
assert(!VT.isVector() && "No default SetCC type for vectors!");
|
2012-10-10 00:06:12 +08:00
|
|
|
return getPointerTy(0).SimpleTy;
|
2008-03-10 23:42:14 +08:00
|
|
|
}
|
|
|
|
|
2009-12-28 10:40:33 +08:00
|
|
|
MVT::SimpleValueType TargetLowering::getCmpLibcallReturnType() const {
|
|
|
|
return MVT::i32; // return the default value
|
|
|
|
}
|
|
|
|
|
2007-06-26 00:23:39 +08:00
|
|
|
/// getVectorTypeBreakdown - Vector types are broken down into some number of
|
2009-08-12 04:47:22 +08:00
|
|
|
/// legal first class types. For example, MVT::v8f32 maps to 2 MVT::v4f32
|
|
|
|
/// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack.
|
|
|
|
/// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86.
|
2006-03-31 08:28:56 +08:00
|
|
|
///
|
2007-06-26 00:23:39 +08:00
|
|
|
/// This method returns the number of registers needed, and the VT for each
|
2007-06-29 07:29:44 +08:00
|
|
|
/// register. It also returns the VT and quantity of the intermediate values
|
|
|
|
/// before they are promoted/expanded.
|
2006-03-31 08:28:56 +08:00
|
|
|
///
|
2009-08-12 08:36:31 +08:00
|
|
|
unsigned TargetLowering::getVectorTypeBreakdown(LLVMContext &Context, EVT VT,
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT &IntermediateVT,
|
2007-06-29 07:29:44 +08:00
|
|
|
unsigned &NumIntermediates,
|
2012-12-19 19:53:21 +08:00
|
|
|
MVT &RegisterVT) const {
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
// If there is a wider vector type with the same element type as this one,
|
2012-04-22 04:08:32 +08:00
|
|
|
// or a promoted vector type that has the same number of elements which
|
|
|
|
// are wider, then we should convert to that legal vector type.
|
|
|
|
// This handles things like <2 x float> -> <4 x float> and
|
|
|
|
// <4 x i1> -> <4 x i32>.
|
|
|
|
LegalizeTypeAction TA = getTypeAction(Context, VT);
|
|
|
|
if (NumElts != 1 && (TA == TypeWidenVector || TA == TypePromoteInteger)) {
|
2012-12-19 19:53:21 +08:00
|
|
|
EVT RegisterEVT = getTypeToTransformTo(Context, VT);
|
|
|
|
if (isTypeLegal(RegisterEVT)) {
|
|
|
|
IntermediateVT = RegisterEVT;
|
|
|
|
RegisterVT = RegisterEVT.getSimpleVT();
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
NumIntermediates = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
// Figure out the right, legal destination reg to copy into.
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT EltTy = VT.getVectorElementType();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-03-31 08:28:56 +08:00
|
|
|
unsigned NumVectorRegs = 1;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
// FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we
|
2007-11-28 03:28:48 +08:00
|
|
|
// could break down into LHS/RHS like LegalizeDAG does.
|
|
|
|
if (!isPowerOf2_32(NumElts)) {
|
|
|
|
NumVectorRegs = NumElts;
|
|
|
|
NumElts = 1;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-03-31 08:28:56 +08: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.
|
2009-08-12 08:36:31 +08:00
|
|
|
while (NumElts > 1 && !isTypeLegal(
|
|
|
|
EVT::getVectorVT(Context, EltTy, NumElts))) {
|
2006-03-31 08:28:56 +08:00
|
|
|
NumElts >>= 1;
|
|
|
|
NumVectorRegs <<= 1;
|
|
|
|
}
|
2007-06-29 07:29:44 +08:00
|
|
|
|
|
|
|
NumIntermediates = NumVectorRegs;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-08-12 08:36:31 +08:00
|
|
|
EVT NewVT = EVT::getVectorVT(Context, EltTy, NumElts);
|
2007-06-26 00:23:39 +08:00
|
|
|
if (!isTypeLegal(NewVT))
|
|
|
|
NewVT = EltTy;
|
2007-06-29 07:29:44 +08:00
|
|
|
IntermediateVT = NewVT;
|
2006-03-31 08:28:56 +08:00
|
|
|
|
2012-12-19 19:53:21 +08:00
|
|
|
MVT DestVT = getRegisterType(Context, NewVT);
|
2007-06-29 07:29:44 +08:00
|
|
|
RegisterVT = DestVT;
|
2011-06-12 22:56:55 +08:00
|
|
|
unsigned NewVTSize = NewVT.getSizeInBits();
|
|
|
|
|
|
|
|
// Convert sizes such as i33 to i64.
|
|
|
|
if (!isPowerOf2_32(NewVTSize))
|
|
|
|
NewVTSize = NextPowerOf2(NewVTSize);
|
|
|
|
|
2012-12-19 19:53:21 +08:00
|
|
|
if (EVT(DestVT).bitsLT(NewVT)) // Value is expanded, e.g. i64 -> i16.
|
2011-06-12 22:56:55 +08:00
|
|
|
return NumVectorRegs*(NewVTSize/DestVT.getSizeInBits());
|
2010-11-23 11:31:01 +08:00
|
|
|
|
Change handling of illegal vector types to widen when possible instead of
expanding: e.g. <2 x float> -> <4 x float> instead of -> 2 floats. This
affects two places in the code: handling cross block values and handling
function return and arguments. Since vectors are already widened by
legalizetypes, this gives us much better code and unblocks x86-64 abi
and SPU abi work.
For example, this (which is a silly example of a cross-block value):
define <4 x float> @test2(<4 x float> %A) nounwind {
%B = shufflevector <4 x float> %A, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%C = fadd <2 x float> %B, %B
br label %BB
BB:
%D = fadd <2 x float> %C, %C
%E = shufflevector <2 x float> %D, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x float> %E
}
Now compiles into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
addps %xmm0, %xmm0
ret
previously it compiled into:
_test2: ## @test2
## BB#0:
addps %xmm0, %xmm0
pshufd $1, %xmm0, %xmm1
## kill: XMM0<def> XMM0<kill> XMM0<def>
insertps $0, %xmm0, %xmm0
insertps $16, %xmm1, %xmm0
addps %xmm0, %xmm0
ret
This implements rdar://8230384
llvm-svn: 112101
2010-08-26 06:49:25 +08:00
|
|
|
// Otherwise, promotion or legal types use the same number of registers as
|
|
|
|
// the vector decimated to the appropriate level.
|
|
|
|
return NumVectorRegs;
|
2006-03-31 08:28:56 +08:00
|
|
|
}
|
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
/// Get the EVTs and ArgFlags collections that represent the legalized return
|
2010-07-10 17:00:22 +08:00
|
|
|
/// type of the given function. This does not require a DAG or a return value,
|
|
|
|
/// and is suitable for use before any DAGs for the function are constructed.
|
|
|
|
/// TODO: Move this out of TargetLowering.cpp.
|
2012-12-30 21:01:51 +08:00
|
|
|
void llvm::GetReturnInfo(Type* ReturnType, AttributeSet attr,
|
2010-07-10 17:00:22 +08:00
|
|
|
SmallVectorImpl<ISD::OutputArg> &Outs,
|
2012-05-25 08:09:29 +08:00
|
|
|
const TargetLowering &TLI) {
|
2010-07-10 17:00:22 +08:00
|
|
|
SmallVector<EVT, 4> ValueVTs;
|
|
|
|
ComputeValueVTs(TLI, ReturnType, ValueVTs);
|
|
|
|
unsigned NumValues = ValueVTs.size();
|
|
|
|
if (NumValues == 0) return;
|
|
|
|
|
|
|
|
for (unsigned j = 0, f = NumValues; j != f; ++j) {
|
|
|
|
EVT VT = ValueVTs[j];
|
|
|
|
ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
|
|
|
|
|
2012-12-30 21:01:51 +08:00
|
|
|
if (attr.hasAttribute(AttributeSet::ReturnIndex, Attribute::SExt))
|
2010-07-10 17:00:22 +08:00
|
|
|
ExtendKind = ISD::SIGN_EXTEND;
|
2012-12-30 21:01:51 +08:00
|
|
|
else if (attr.hasAttribute(AttributeSet::ReturnIndex, Attribute::ZExt))
|
2010-07-10 17:00:22 +08:00
|
|
|
ExtendKind = ISD::ZERO_EXTEND;
|
|
|
|
|
|
|
|
// FIXME: C calling convention requires the return type to be promoted to
|
|
|
|
// at least 32-bit. But this is not necessary for non-C calling
|
|
|
|
// conventions. The frontend should mark functions whose return values
|
|
|
|
// require promoting with signext or zeroext attributes.
|
|
|
|
if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) {
|
2012-12-19 19:48:16 +08:00
|
|
|
MVT MinVT = TLI.getRegisterType(ReturnType->getContext(), MVT::i32);
|
2010-07-10 17:00:22 +08:00
|
|
|
if (VT.bitsLT(MinVT))
|
|
|
|
VT = MinVT;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT);
|
2012-12-19 19:48:16 +08:00
|
|
|
MVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT);
|
2010-07-10 17:00:22 +08:00
|
|
|
|
|
|
|
// 'inreg' on function refers to return value
|
|
|
|
ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
|
2012-12-30 21:01:51 +08:00
|
|
|
if (attr.hasAttribute(AttributeSet::ReturnIndex, Attribute::InReg))
|
2010-07-10 17:00:22 +08:00
|
|
|
Flags.setInReg();
|
|
|
|
|
|
|
|
// Propagate extension type if any
|
2012-12-30 21:01:51 +08:00
|
|
|
if (attr.hasAttribute(AttributeSet::ReturnIndex, Attribute::SExt))
|
2010-07-10 17:00:22 +08:00
|
|
|
Flags.setSExt();
|
2012-12-30 21:01:51 +08:00
|
|
|
else if (attr.hasAttribute(AttributeSet::ReturnIndex, Attribute::ZExt))
|
2010-07-10 17:00:22 +08:00
|
|
|
Flags.setZExt();
|
|
|
|
|
2012-09-20 07:35:21 +08:00
|
|
|
for (unsigned i = 0; i < NumParts; ++i)
|
2012-11-02 07:49:58 +08:00
|
|
|
Outs.push_back(ISD::OutputArg(Flags, PartVT, /*isFixed=*/true, 0, 0));
|
2010-07-10 17:00:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-24 08:22:01 +08:00
|
|
|
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
|
2008-02-29 06:31:51 +08:00
|
|
|
/// function arguments in the caller parameter area. This is the actual
|
|
|
|
/// alignment, not its logarithm.
|
2011-07-18 12:54:35 +08:00
|
|
|
unsigned TargetLowering::getByValTypeAlignment(Type *Ty) const {
|
2008-02-29 06:31:51 +08:00
|
|
|
return TD->getCallFrameTypeAlignment(Ty);
|
2008-01-24 08:22:01 +08:00
|
|
|
}
|
|
|
|
|
2010-01-26 07:26:13 +08:00
|
|
|
/// getJumpTableEncoding - Return the entry encoding for a jump table in the
|
|
|
|
/// current function. The returned value is a member of the
|
|
|
|
/// MachineJumpTableInfo::JTEntryKind enum.
|
|
|
|
unsigned TargetLowering::getJumpTableEncoding() const {
|
|
|
|
// In non-pic modes, just use the address of a block.
|
|
|
|
if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
|
|
|
|
return MachineJumpTableInfo::EK_BlockAddress;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-01-26 07:26:13 +08:00
|
|
|
// In PIC mode, if the target supports a GPRel32 directive, use it.
|
|
|
|
if (getTargetMachine().getMCAsmInfo()->getGPRel32Directive() != 0)
|
|
|
|
return MachineJumpTableInfo::EK_GPRel32BlockAddress;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-01-26 07:26:13 +08:00
|
|
|
// Otherwise, use a label difference.
|
|
|
|
return MachineJumpTableInfo::EK_LabelDifference32;
|
|
|
|
}
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table,
|
|
|
|
SelectionDAG &DAG) const {
|
2010-01-26 14:53:37 +08:00
|
|
|
// If our PIC model is GP relative, use the global offset table as the base.
|
2012-04-10 04:32:12 +08:00
|
|
|
unsigned JTEncoding = getJumpTableEncoding();
|
|
|
|
|
|
|
|
if ((JTEncoding == MachineJumpTableInfo::EK_GPRel64BlockAddress) ||
|
|
|
|
(JTEncoding == MachineJumpTableInfo::EK_GPRel32BlockAddress))
|
2012-10-10 00:06:12 +08:00
|
|
|
return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy(0));
|
2012-04-10 04:32:12 +08:00
|
|
|
|
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
llvm-svn: 43924
2007-11-09 09:32:10 +08:00
|
|
|
return Table;
|
|
|
|
}
|
|
|
|
|
2010-01-26 13:30:30 +08:00
|
|
|
/// getPICJumpTableRelocBaseExpr - This returns the relocation base for the
|
|
|
|
/// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an
|
|
|
|
/// MCExpr.
|
|
|
|
const MCExpr *
|
2010-01-26 14:28:43 +08:00
|
|
|
TargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF,
|
|
|
|
unsigned JTI,MCContext &Ctx) const{
|
2010-01-26 13:58:28 +08:00
|
|
|
// The normal PIC reloc base is the label at the start of the jump table.
|
2010-01-26 14:28:43 +08:00
|
|
|
return MCSymbolRefExpr::Create(MF->getJTISymbol(JTI, Ctx), Ctx);
|
2010-01-26 13:30:30 +08:00
|
|
|
}
|
|
|
|
|
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.
llvm-svn: 57748
2008-10-18 10:06:02 +08: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() &&
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
!GA->getGlobal()->isWeakForLinker())
|
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.
llvm-svn: 57748
2008-10-18 10:06:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
// Otherwise assume nothing is safe.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Switch TargetTransformInfo from an immutable analysis pass that requires
a TargetMachine to construct (and thus isn't always available), to an
analysis group that supports layered implementations much like
AliasAnalysis does. This is a pretty massive change, with a few parts
that I was unable to easily separate (sorry), so I'll walk through it.
The first step of this conversion was to make TargetTransformInfo an
analysis group, and to sink the nonce implementations in
ScalarTargetTransformInfo and VectorTargetTranformInfo into
a NoTargetTransformInfo pass. This allows other passes to add a hard
requirement on TTI, and assume they will always get at least on
implementation.
The TargetTransformInfo analysis group leverages the delegation chaining
trick that AliasAnalysis uses, where the base class for the analysis
group delegates to the previous analysis *pass*, allowing all but tho
NoFoo analysis passes to only implement the parts of the interfaces they
support. It also introduces a new trick where each pass in the group
retains a pointer to the top-most pass that has been initialized. This
allows passes to implement one API in terms of another API and benefit
when some other pass above them in the stack has more precise results
for the second API.
The second step of this conversion is to create a pass that implements
the TargetTransformInfo analysis using the target-independent
abstractions in the code generator. This replaces the
ScalarTargetTransformImpl and VectorTargetTransformImpl classes in
lib/Target with a single pass in lib/CodeGen called
BasicTargetTransformInfo. This class actually provides most of the TTI
functionality, basing it upon the TargetLowering abstraction and other
information in the target independent code generator.
The third step of the conversion adds support to all TargetMachines to
register custom analysis passes. This allows building those passes with
access to TargetLowering or other target-specific classes, and it also
allows each target to customize the set of analysis passes desired in
the pass manager. The baseline LLVMTargetMachine implements this
interface to add the BasicTTI pass to the pass manager, and all of the
tools that want to support target-aware TTI passes call this routine on
whatever target machine they end up with to add the appropriate passes.
The fourth step of the conversion created target-specific TTI analysis
passes for the X86 and ARM backends. These passes contain the custom
logic that was previously in their extensions of the
ScalarTargetTransformInfo and VectorTargetTransformInfo interfaces.
I separated them into their own file, as now all of the interface bits
are private and they just expose a function to create the pass itself.
Then I extended these target machines to set up a custom set of analysis
passes, first adding BasicTTI as a fallback, and then adding their
customized TTI implementations.
The fourth step required logic that was shared between the target
independent layer and the specific targets to move to a different
interface, as they no longer derive from each other. As a consequence,
a helper functions were added to TargetLowering representing the common
logic needed both in the target implementation and the codegen
implementation of the TTI pass. While technically this is the only
change that could have been committed separately, it would have been
a nightmare to extract.
The final step of the conversion was just to delete all the old
boilerplate. This got rid of the ScalarTargetTransformInfo and
VectorTargetTransformInfo classes, all of the support in all of the
targets for producing instances of them, and all of the support in the
tools for manually constructing a pass based around them.
Now that TTI is a relatively normal analysis group, two things become
straightforward. First, we can sink it into lib/Analysis which is a more
natural layer for it to live. Second, clients of this interface can
depend on it *always* being available which will simplify their code and
behavior. These (and other) simplifications will follow in subsequent
commits, this one is clearly big enough.
Finally, I'm very aware that much of the comments and documentation
needs to be updated. As soon as I had this working, and plausibly well
commented, I wanted to get it committed and in front of the build bots.
I'll be doing a few passes over documentation later if it sticks.
Commits to update DragonEgg and Clang will be made presently.
llvm-svn: 171681
2013-01-07 09:37:14 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TargetTransformInfo Helpers
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
int TargetLowering::InstructionOpcodeToISD(unsigned Opcode) const {
|
|
|
|
enum InstructionOpcodes {
|
|
|
|
#define HANDLE_INST(NUM, OPCODE, CLASS) OPCODE = NUM,
|
|
|
|
#define LAST_OTHER_INST(NUM) InstructionOpcodesCount = NUM
|
|
|
|
#include "llvm/IR/Instruction.def"
|
|
|
|
};
|
|
|
|
switch (static_cast<InstructionOpcodes>(Opcode)) {
|
|
|
|
case Ret: return 0;
|
|
|
|
case Br: return 0;
|
|
|
|
case Switch: return 0;
|
|
|
|
case IndirectBr: return 0;
|
|
|
|
case Invoke: return 0;
|
|
|
|
case Resume: return 0;
|
|
|
|
case Unreachable: return 0;
|
|
|
|
case Add: return ISD::ADD;
|
|
|
|
case FAdd: return ISD::FADD;
|
|
|
|
case Sub: return ISD::SUB;
|
|
|
|
case FSub: return ISD::FSUB;
|
|
|
|
case Mul: return ISD::MUL;
|
|
|
|
case FMul: return ISD::FMUL;
|
|
|
|
case UDiv: return ISD::UDIV;
|
|
|
|
case SDiv: return ISD::UDIV;
|
|
|
|
case FDiv: return ISD::FDIV;
|
|
|
|
case URem: return ISD::UREM;
|
|
|
|
case SRem: return ISD::SREM;
|
|
|
|
case FRem: return ISD::FREM;
|
|
|
|
case Shl: return ISD::SHL;
|
|
|
|
case LShr: return ISD::SRL;
|
|
|
|
case AShr: return ISD::SRA;
|
|
|
|
case And: return ISD::AND;
|
|
|
|
case Or: return ISD::OR;
|
|
|
|
case Xor: return ISD::XOR;
|
|
|
|
case Alloca: return 0;
|
|
|
|
case Load: return ISD::LOAD;
|
|
|
|
case Store: return ISD::STORE;
|
|
|
|
case GetElementPtr: return 0;
|
|
|
|
case Fence: return 0;
|
|
|
|
case AtomicCmpXchg: return 0;
|
|
|
|
case AtomicRMW: return 0;
|
|
|
|
case Trunc: return ISD::TRUNCATE;
|
|
|
|
case ZExt: return ISD::ZERO_EXTEND;
|
|
|
|
case SExt: return ISD::SIGN_EXTEND;
|
|
|
|
case FPToUI: return ISD::FP_TO_UINT;
|
|
|
|
case FPToSI: return ISD::FP_TO_SINT;
|
|
|
|
case UIToFP: return ISD::UINT_TO_FP;
|
|
|
|
case SIToFP: return ISD::SINT_TO_FP;
|
|
|
|
case FPTrunc: return ISD::FP_ROUND;
|
|
|
|
case FPExt: return ISD::FP_EXTEND;
|
|
|
|
case PtrToInt: return ISD::BITCAST;
|
|
|
|
case IntToPtr: return ISD::BITCAST;
|
|
|
|
case BitCast: return ISD::BITCAST;
|
|
|
|
case ICmp: return ISD::SETCC;
|
|
|
|
case FCmp: return ISD::SETCC;
|
|
|
|
case PHI: return 0;
|
|
|
|
case Call: return 0;
|
|
|
|
case Select: return ISD::SELECT;
|
|
|
|
case UserOp1: return 0;
|
|
|
|
case UserOp2: return 0;
|
|
|
|
case VAArg: return 0;
|
|
|
|
case ExtractElement: return ISD::EXTRACT_VECTOR_ELT;
|
|
|
|
case InsertElement: return ISD::INSERT_VECTOR_ELT;
|
|
|
|
case ShuffleVector: return ISD::VECTOR_SHUFFLE;
|
|
|
|
case ExtractValue: return ISD::MERGE_VALUES;
|
|
|
|
case InsertValue: return ISD::MERGE_VALUES;
|
|
|
|
case LandingPad: return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Unknown instruction type encountered!");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<unsigned, MVT>
|
|
|
|
TargetLowering::getTypeLegalizationCost(Type *Ty) const {
|
|
|
|
LLVMContext &C = Ty->getContext();
|
|
|
|
EVT MTy = getValueType(Ty);
|
|
|
|
|
|
|
|
unsigned Cost = 1;
|
|
|
|
// We keep legalizing the type until we find a legal kind. We assume that
|
|
|
|
// the only operation that costs anything is the split. After splitting
|
|
|
|
// we need to handle two types.
|
|
|
|
while (true) {
|
|
|
|
LegalizeKind LK = getTypeConversion(C, MTy);
|
|
|
|
|
|
|
|
if (LK.first == TypeLegal)
|
|
|
|
return std::make_pair(Cost, MTy.getSimpleVT());
|
|
|
|
|
|
|
|
if (LK.first == TypeSplitVector || LK.first == TypeExpandInteger)
|
|
|
|
Cost *= 2;
|
|
|
|
|
|
|
|
// Keep legalizing the type.
|
|
|
|
MTy = LK.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-04 10:13:02 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Optimization Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
/// ShrinkDemandedConstant - Check to see if the specified operand of the
|
2006-02-17 05:11:51 +08:00
|
|
|
/// 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.
|
2010-11-23 11:31:01 +08:00
|
|
|
bool TargetLowering::TargetLoweringOpt::ShrinkDemandedConstant(SDValue Op,
|
2008-02-27 08:25:32 +08:00
|
|
|
const APInt &Demanded) {
|
2009-02-07 05:50:26 +08:00
|
|
|
DebugLoc dl = Op.getDebugLoc();
|
2009-03-04 08:18:06 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// FIXME: ISD::SELECT, ISD::SELECT_CC
|
2009-01-29 09:59:02 +08:00
|
|
|
switch (Op.getOpcode()) {
|
2006-02-17 05:11:51 +08:00
|
|
|
default: break;
|
|
|
|
case ISD::XOR:
|
2009-03-04 08:18:06 +08:00
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR: {
|
|
|
|
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
|
|
|
|
if (!C) return false;
|
|
|
|
|
|
|
|
if (Op.getOpcode() == ISD::XOR &&
|
|
|
|
(C->getAPIntValue() | (~Demanded)).isAllOnesValue())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// if we can expand it to have all bits set, do it
|
|
|
|
if (C->getAPIntValue().intersects(~Demanded)) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2009-03-04 08:18:06 +08:00
|
|
|
SDValue New = DAG.getNode(Op.getOpcode(), dl, VT, Op.getOperand(0),
|
|
|
|
DAG.getConstant(Demanded &
|
2010-11-23 11:31:01 +08:00
|
|
|
C->getAPIntValue(),
|
2009-03-04 08:18:06 +08:00
|
|
|
VT));
|
|
|
|
return CombineTo(Op, New);
|
|
|
|
}
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-03-04 08:18:06 +08:00
|
|
|
}
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
/// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the
|
|
|
|
/// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening
|
|
|
|
/// cast, but it could be generalized for targets with other types of
|
|
|
|
/// implicit widening casts.
|
|
|
|
bool
|
|
|
|
TargetLowering::TargetLoweringOpt::ShrinkDemandedOp(SDValue Op,
|
|
|
|
unsigned BitWidth,
|
|
|
|
const APInt &Demanded,
|
|
|
|
DebugLoc dl) {
|
|
|
|
assert(Op.getNumOperands() == 2 &&
|
|
|
|
"ShrinkDemandedOp only supports binary operators!");
|
|
|
|
assert(Op.getNode()->getNumValues() == 1 &&
|
|
|
|
"ShrinkDemandedOp only supports nodes with one result!");
|
|
|
|
|
|
|
|
// Don't do this if the node has another user, which may require the
|
|
|
|
// full value.
|
|
|
|
if (!Op.getNode()->hasOneUse())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Search for the smallest integer type with free casts to and from
|
|
|
|
// Op's type. For expedience, just check power-of-2 integer types.
|
|
|
|
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
2012-12-19 15:39:08 +08:00
|
|
|
unsigned DemandedSize = BitWidth - Demanded.countLeadingZeros();
|
|
|
|
unsigned SmallVTBits = DemandedSize;
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
if (!isPowerOf2_32(SmallVTBits))
|
|
|
|
SmallVTBits = NextPowerOf2(SmallVTBits);
|
|
|
|
for (; SmallVTBits < BitWidth; SmallVTBits = NextPowerOf2(SmallVTBits)) {
|
2009-08-12 08:36:31 +08:00
|
|
|
EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), SmallVTBits);
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
if (TLI.isTruncateFree(Op.getValueType(), SmallVT) &&
|
|
|
|
TLI.isZExtFree(SmallVT, Op.getValueType())) {
|
|
|
|
// We found a type with free casts.
|
|
|
|
SDValue X = DAG.getNode(Op.getOpcode(), dl, SmallVT,
|
|
|
|
DAG.getNode(ISD::TRUNCATE, dl, SmallVT,
|
|
|
|
Op.getNode()->getOperand(0)),
|
|
|
|
DAG.getNode(ISD::TRUNCATE, dl, SmallVT,
|
|
|
|
Op.getNode()->getOperand(1)));
|
2012-12-19 15:39:08 +08:00
|
|
|
bool NeedZext = DemandedSize > SmallVTBits;
|
|
|
|
SDValue Z = DAG.getNode(NeedZext ? ISD::ZERO_EXTEND : ISD::ANY_EXTEND,
|
|
|
|
dl, Op.getValueType(), X);
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
return CombineTo(Op, Z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
/// SimplifyDemandedBits - Look at Op. At this point, we know that only the
|
2011-06-11 10:27:46 +08:00
|
|
|
/// DemandedMask bits of the result of Op are ever used downstream. If we can
|
2006-02-17 05:11:51 +08:00
|
|
|
/// 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-28 05:46:04 +08:00
|
|
|
bool TargetLowering::SimplifyDemandedBits(SDValue Op,
|
2008-02-27 08:25:32 +08:00
|
|
|
const APInt &DemandedMask,
|
|
|
|
APInt &KnownZero,
|
|
|
|
APInt &KnownOne,
|
2006-02-17 05:11:51 +08:00
|
|
|
TargetLoweringOpt &TLO,
|
|
|
|
unsigned Depth) const {
|
2008-02-27 08:25:32 +08:00
|
|
|
unsigned BitWidth = DemandedMask.getBitWidth();
|
2009-12-12 05:31:27 +08:00
|
|
|
assert(Op.getValueType().getScalarType().getSizeInBits() == BitWidth &&
|
2008-02-27 08:25:32 +08:00
|
|
|
"Mask size mismatches value type size!");
|
|
|
|
APInt NewMask = DemandedMask;
|
2009-02-08 03:59:05 +08:00
|
|
|
DebugLoc dl = Op.getDebugLoc();
|
2008-02-27 08:25:32 +08:00
|
|
|
|
|
|
|
// Don't know anything.
|
|
|
|
KnownZero = KnownOne = APInt(BitWidth, 0);
|
2007-05-18 02:19:23 +08:00
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// Other users may use these bits.
|
2010-11-23 11:31:01 +08:00
|
|
|
if (!Op.getNode()->hasOneUse()) {
|
2006-02-17 05:11:51 +08:00
|
|
|
if (Depth != 0) {
|
2010-11-23 11:31:01 +08:00
|
|
|
// If not at the root, Just compute the KnownZero/KnownOne bits to
|
2006-02-17 05:11:51 +08:00
|
|
|
// simplify things downstream.
|
2012-04-04 20:51:34 +08:00
|
|
|
TLO.DAG.ComputeMaskedBits(Op, KnownZero, KnownOne, Depth);
|
2006-02-17 05:11:51 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// If this is the root being simplified, allow it to have multiple uses,
|
2008-02-27 08:25:32 +08:00
|
|
|
// just set the NewMask to all bits.
|
|
|
|
NewMask = APInt::getAllOnesValue(BitWidth);
|
2010-11-23 11:31:01 +08:00
|
|
|
} else if (DemandedMask == 0) {
|
2006-02-17 05:11:51 +08:00
|
|
|
// Not demanding any bits from Op.
|
|
|
|
if (Op.getOpcode() != ISD::UNDEF)
|
2009-02-07 07:05:02 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getUNDEF(Op.getValueType()));
|
2006-02-04 06:24:05 +08:00
|
|
|
return false;
|
2006-02-17 05:11:51 +08:00
|
|
|
} else if (Depth == 6) { // Limit search depth.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut;
|
2006-02-04 06:24:05 +08:00
|
|
|
switch (Op.getOpcode()) {
|
2006-02-17 05:11:51 +08:00
|
|
|
case ISD::Constant:
|
|
|
|
// We know all of the bits for a constant!
|
2012-04-04 20:51:34 +08:00
|
|
|
KnownOne = cast<ConstantSDNode>(Op)->getAPIntValue();
|
|
|
|
KnownZero = ~KnownOne;
|
2006-02-27 07:36:02 +08:00
|
|
|
return false; // Don't fall through, will infinitely loop.
|
2006-02-04 06:24:05 +08:00
|
|
|
case ISD::AND:
|
2006-02-27 08:36:27 +08: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 08:25:32 +08:00
|
|
|
APInt LHSZero, LHSOne;
|
2011-01-11 05:53:07 +08:00
|
|
|
// Do not increment Depth here; that can cause an infinite loop.
|
2012-04-04 20:51:34 +08:00
|
|
|
TLO.DAG.ComputeMaskedBits(Op.getOperand(0), LHSZero, LHSOne, Depth);
|
2006-02-27 08:36:27 +08:00
|
|
|
// If the LHS already has zeros where RHSC does, this and is dead.
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask))
|
2006-02-27 08:36:27 +08: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 08:25:32 +08:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask))
|
2006-02-27 08:36:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), ~KnownZero & NewMask,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// 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 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask))
|
2006-02-17 05:11:51 +08: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 08:25:32 +08:00
|
|
|
if ((NewMask & (KnownZero|KnownZero2)) == NewMask)
|
2006-02-17 05:11:51 +08: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 08:25:32 +08:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, ~KnownZero2 & NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return true;
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
// If the operation can be done in a smaller type, do so.
|
2010-06-24 22:30:44 +08:00
|
|
|
if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl))
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
return true;
|
|
|
|
|
2006-02-17 05:11:51 +08: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:
|
2010-11-23 11:31:01 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), ~KnownOne & NewMask,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// 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 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownOne2 & KnownZero) == (~KnownOne2 & NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownOne & KnownZero2) == (~KnownOne & NewMask))
|
2006-02-17 05:11:51 +08: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 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return true;
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
// If the operation can be done in a smaller type, do so.
|
2010-06-24 22:30:44 +08:00
|
|
|
if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl))
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
return true;
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// 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:
|
2010-11-23 11:31:01 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), NewMask, KnownZero2,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// 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 08:25:32 +08:00
|
|
|
if ((KnownZero & NewMask) == NewMask)
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((KnownZero2 & NewMask) == NewMask)
|
2006-02-17 05:11:51 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
// If the operation can be done in a smaller type, do so.
|
2010-06-24 22:30:44 +08:00
|
|
|
if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl))
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
return true;
|
|
|
|
|
2006-11-28 05:50:02 +08: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.
|
2012-09-27 18:14:43 +08:00
|
|
|
// e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((NewMask & ~KnownZero & ~KnownZero2) == 0)
|
2009-02-07 05:50:26 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, Op.getValueType(),
|
2006-11-28 05:50:02 +08:00
|
|
|
Op.getOperand(0),
|
|
|
|
Op.getOperand(1)));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-17 05:11:51 +08: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);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// 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.
|
2012-09-27 18:14:43 +08:00
|
|
|
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
|
2012-04-18 06:23:10 +08:00
|
|
|
// NB: it is okay if more bits are known than are requested
|
|
|
|
if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known on one side
|
|
|
|
if (KnownOne == KnownOne2) { // set bits are the same on both sides
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ANDC = TLO.DAG.getConstant(~KnownOne & NewMask, VT);
|
2010-11-23 11:31:01 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, dl, VT,
|
2009-02-03 08:47:48 +08:00
|
|
|
Op.getOperand(0), ANDC));
|
2006-02-17 05:11:51 +08:00
|
|
|
}
|
2006-02-04 06:24:05 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2008-04-07 05:23:02 +08: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()) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2009-02-03 08:47:48 +08:00
|
|
|
SDValue New = TLO.DAG.getNode(Op.getOpcode(), dl,VT, Op.getOperand(0),
|
2008-04-07 05:23:02 +08: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-17 05:11:51 +08:00
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
KnownOne = KnownOneOut;
|
|
|
|
break;
|
|
|
|
case ISD::SELECT:
|
2010-11-23 11:31:01 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero2,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// If the operands are constants, see if we can simplify them.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-17 05:11:51 +08:00
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
break;
|
|
|
|
case ISD::SELECT_CC:
|
2010-11-23 11:31:01 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(3), NewMask, KnownZero,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero2,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If the operands are constants, see if we can simplify them.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (TLO.ShrinkDemandedConstant(Op, NewMask))
|
2006-02-27 07:36:02 +08:00
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
2006-02-04 06:24:05 +08:00
|
|
|
break;
|
|
|
|
case ISD::SHL:
|
2006-02-17 05:11:51 +08:00
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2008-09-13 00:56:44 +08:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2008-07-28 05:46:04 +08: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
llvm-svn: 36221
2007-04-18 05:14:16 +08:00
|
|
|
|
2008-02-27 08:25:32 +08: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
llvm-svn: 36221
2007-04-18 05:14:16 +08: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 08:25:32 +08:00
|
|
|
if (ShAmt && (NewMask & APInt::getLowBitsSet(BitWidth, ShAmt)) == 0) {
|
2008-09-13 00:56:44 +08: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
llvm-svn: 36221
2007-04-18 05:14:16 +08:00
|
|
|
unsigned Opc = ISD::SHL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SRL;
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue NewSA =
|
2007-05-31 00:30:06 +08:00
|
|
|
TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2009-02-03 08:47:48 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, 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
llvm-svn: 36221
2007-04-18 05:14:16 +08:00
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
|
|
|
|
2010-07-24 02:03:30 +08:00
|
|
|
if (SimplifyDemandedBits(InOp, NewMask.lshr(ShAmt),
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-07-24 02:03:30 +08:00
|
|
|
|
|
|
|
// Convert (shl (anyext x, c)) to (anyext (shl x, c)) if the high bits
|
|
|
|
// are not demanded. This will likely allow the anyext to be folded away.
|
|
|
|
if (InOp.getNode()->getOpcode() == ISD::ANY_EXTEND) {
|
|
|
|
SDValue InnerOp = InOp.getNode()->getOperand(0);
|
|
|
|
EVT InnerVT = InnerOp.getValueType();
|
2011-12-09 09:16:26 +08:00
|
|
|
unsigned InnerBits = InnerVT.getSizeInBits();
|
|
|
|
if (ShAmt < InnerBits && NewMask.lshr(InnerBits) == 0 &&
|
2010-07-24 02:03:30 +08:00
|
|
|
isTypeDesirableForOp(ISD::SHL, InnerVT)) {
|
2011-02-26 05:41:48 +08:00
|
|
|
EVT ShTy = getShiftAmountTy(InnerVT);
|
2010-07-24 05:08:12 +08:00
|
|
|
if (!APInt(BitWidth, ShAmt).isIntN(ShTy.getSizeInBits()))
|
|
|
|
ShTy = InnerVT;
|
2010-07-24 02:03:30 +08:00
|
|
|
SDValue NarrowShl =
|
|
|
|
TLO.DAG.getNode(ISD::SHL, dl, InnerVT, InnerOp,
|
2010-07-24 05:08:12 +08:00
|
|
|
TLO.DAG.getConstant(ShAmt, ShTy));
|
2010-07-24 02:03:30 +08:00
|
|
|
return
|
|
|
|
TLO.CombineTo(Op,
|
|
|
|
TLO.DAG.getNode(ISD::ANY_EXTEND, dl, Op.getValueType(),
|
|
|
|
NarrowShl));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-13 00:56:44 +08:00
|
|
|
KnownZero <<= SA->getZExtValue();
|
|
|
|
KnownOne <<= SA->getZExtValue();
|
2008-02-27 08:25:32 +08:00
|
|
|
// low bits known zero.
|
2008-09-13 00:56:44 +08:00
|
|
|
KnownZero |= APInt::getLowBitsSet(BitWidth, SA->getZExtValue());
|
2006-02-17 05:11:51 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRL:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2008-09-13 00:56:44 +08:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned VTSize = VT.getSizeInBits();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue InOp = Op.getOperand(0);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08: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
llvm-svn: 36221
2007-04-18 05:14:16 +08: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 08:25:32 +08:00
|
|
|
if (ShAmt && (NewMask & APInt::getHighBitsSet(VTSize, ShAmt)) == 0) {
|
2008-09-13 00:56:44 +08: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
llvm-svn: 36221
2007-04-18 05:14:16 +08:00
|
|
|
unsigned Opc = ISD::SRL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SHL;
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue NewSA =
|
2007-04-18 06:53:02 +08:00
|
|
|
TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
|
2009-02-03 08:47:48 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, 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
llvm-svn: 36221
2007-04-18 05:14:16 +08:00
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
// Compute the new bits that are at the top now.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(InOp, (NewMask << ShAmt),
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 08:25:32 +08:00
|
|
|
KnownZero = KnownZero.lshr(ShAmt);
|
|
|
|
KnownOne = KnownOne.lshr(ShAmt);
|
2006-06-14 00:52:37 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);
|
2006-06-14 00:52:37 +08:00
|
|
|
KnownZero |= HighBits; // High bits known zero.
|
2006-02-17 05:11:51 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRA:
|
2009-01-29 09:59:02 +08:00
|
|
|
// If this is an arithmetic shift right and only the low-bit is set, we can
|
|
|
|
// always convert this into a logical shr, even if the shift amount is
|
|
|
|
// variable. The low bit of the shift cannot be an input sign bit unless
|
|
|
|
// the shift amount is >= the size of the datatype, which is undefined.
|
2011-12-09 09:16:26 +08:00
|
|
|
if (NewMask == 1)
|
2010-04-17 14:13:15 +08:00
|
|
|
return TLO.CombineTo(Op,
|
|
|
|
TLO.DAG.getNode(ISD::SRL, dl, Op.getValueType(),
|
|
|
|
Op.getOperand(0), Op.getOperand(1)));
|
2009-01-29 09:59:02 +08:00
|
|
|
|
2006-02-17 05:11:51 +08:00
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = Op.getValueType();
|
2008-09-13 00:56:44 +08:00
|
|
|
unsigned ShAmt = SA->getZExtValue();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
// If the shift count is an invalid immediate, don't do anything.
|
|
|
|
if (ShAmt >= BitWidth)
|
|
|
|
break;
|
|
|
|
|
|
|
|
APInt InDemandedMask = (NewMask << ShAmt);
|
2006-05-09 01:22:53 +08:00
|
|
|
|
|
|
|
// If any of the demanded bits are produced by the sign extension, we also
|
|
|
|
// demand the input sign bit.
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);
|
|
|
|
if (HighBits.intersects(NewMask))
|
2009-12-12 05:31:27 +08:00
|
|
|
InDemandedMask |= APInt::getSignBit(VT.getScalarType().getSizeInBits());
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-05-09 01:22:53 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask,
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2008-02-27 08:25:32 +08:00
|
|
|
KnownZero = KnownZero.lshr(ShAmt);
|
|
|
|
KnownOne = KnownOne.lshr(ShAmt);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
// Handle the sign bit, adjusted to where it is now in the mask.
|
|
|
|
APInt SignBit = APInt::getSignBit(BitWidth).lshr(ShAmt);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-17 05:11:51 +08: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 08:25:32 +08:00
|
|
|
if (KnownZero.intersects(SignBit) || (HighBits & ~NewMask) == HighBits) {
|
2010-11-23 11:31:01 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, VT,
|
2009-02-03 08:47:48 +08:00
|
|
|
Op.getOperand(0),
|
2006-02-17 05:11:51 +08:00
|
|
|
Op.getOperand(1)));
|
2008-02-27 08:25:32 +08:00
|
|
|
} else if (KnownOne.intersects(SignBit)) { // New bits are known one.
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne |= HighBits;
|
|
|
|
}
|
2006-02-04 06:24:05 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
2012-01-16 03:27:55 +08:00
|
|
|
EVT ExVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
|
|
|
|
|
|
|
APInt MsbMask = APInt::getHighBitsSet(BitWidth, 1);
|
|
|
|
// If we only care about the highest bit, don't bother shifting right.
|
2012-01-31 09:08:03 +08:00
|
|
|
if (MsbMask == DemandedMask) {
|
2012-01-16 03:27:55 +08:00
|
|
|
unsigned ShAmt = ExVT.getScalarType().getSizeInBits();
|
|
|
|
SDValue InOp = Op.getOperand(0);
|
2012-01-31 09:08:03 +08:00
|
|
|
|
|
|
|
// Compute the correct shift amount type, which must be getShiftAmountTy
|
|
|
|
// for scalar types after legalization.
|
|
|
|
EVT ShiftAmtTy = Op.getValueType();
|
|
|
|
if (TLO.LegalTypes() && !ShiftAmtTy.isVector())
|
|
|
|
ShiftAmtTy = getShiftAmountTy(ShiftAmtTy);
|
|
|
|
|
|
|
|
SDValue ShiftAmt = TLO.DAG.getConstant(BitWidth - ShAmt, ShiftAmtTy);
|
2012-01-16 03:27:55 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, dl,
|
|
|
|
Op.getValueType(), InOp, ShiftAmt));
|
|
|
|
}
|
2006-02-17 05:11:51 +08:00
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
// Sign extension. Compute the demanded bits in the result that are not
|
2006-02-17 05:11:51 +08:00
|
|
|
// present in the input.
|
2010-01-09 10:13:55 +08:00
|
|
|
APInt NewBits =
|
|
|
|
APInt::getHighBitsSet(BitWidth,
|
2012-01-16 03:27:55 +08:00
|
|
|
BitWidth - ExVT.getScalarType().getSizeInBits());
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If none of the extended bits are demanded, eliminate the sextinreg.
|
2010-08-02 12:42:25 +08:00
|
|
|
if ((NewBits & NewMask) == 0)
|
2006-02-27 07:36:02 +08:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
|
2010-12-07 16:25:19 +08:00
|
|
|
APInt InSignBit =
|
2012-01-16 03:27:55 +08:00
|
|
|
APInt::getSignBit(ExVT.getScalarType().getSizeInBits()).zext(BitWidth);
|
2010-01-09 10:13:55 +08:00
|
|
|
APInt InputDemandedBits =
|
|
|
|
APInt::getLowBitsSet(BitWidth,
|
2012-01-16 03:27:55 +08:00
|
|
|
ExVT.getScalarType().getSizeInBits()) &
|
2010-01-09 10:13:55 +08:00
|
|
|
NewMask;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// Since the sign extended bits are demanded, we know that the sign
|
2006-02-17 05:11:51 +08:00
|
|
|
// bit is demanded.
|
2006-02-27 07:36:02 +08:00
|
|
|
InputDemandedBits |= InSignBit;
|
2006-02-17 05:11:51 +08:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
2006-02-04 06:24:05 +08:00
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-02-17 05:11:51 +08:00
|
|
|
|
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If the input sign bit is known zero, convert this into a zero extension.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (KnownZero.intersects(InSignBit))
|
2010-11-23 11:31:01 +08:00
|
|
|
return TLO.CombineTo(Op,
|
2012-01-16 03:27:55 +08:00
|
|
|
TLO.DAG.getZeroExtendInReg(Op.getOperand(0),dl,ExVT));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
if (KnownOne.intersects(InSignBit)) { // Input sign bit known set
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
2006-02-27 07:36:02 +08:00
|
|
|
} else { // Input sign bit unknown
|
2006-02-17 05:11:51 +08:00
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
2006-02-04 06:24:05 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-02-27 07:36:02 +08:00
|
|
|
case ISD::ZERO_EXTEND: {
|
2010-01-09 10:13:55 +08:00
|
|
|
unsigned OperandBitWidth =
|
|
|
|
Op.getOperand(0).getValueType().getScalarType().getSizeInBits();
|
2010-12-07 16:25:19 +08:00
|
|
|
APInt InMask = NewMask.trunc(OperandBitWidth);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt NewBits =
|
|
|
|
APInt::getHighBitsSet(BitWidth, BitWidth - OperandBitWidth) & NewMask;
|
|
|
|
if (!NewBits.intersects(NewMask))
|
2009-02-03 08:47:48 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ANY_EXTEND, dl,
|
2010-11-23 11:31:01 +08:00
|
|
|
Op.getValueType(),
|
2006-02-27 07:36:02 +08:00
|
|
|
Op.getOperand(0)));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InMask,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2010-12-07 16:25:19 +08:00
|
|
|
KnownZero = KnownZero.zext(BitWidth);
|
|
|
|
KnownOne = KnownOne.zext(BitWidth);
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownZero |= NewBits;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::SIGN_EXTEND: {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT InVT = Op.getOperand(0).getValueType();
|
2010-01-09 10:13:55 +08:00
|
|
|
unsigned InBits = InVT.getScalarType().getSizeInBits();
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt InMask = APInt::getLowBitsSet(BitWidth, InBits);
|
2008-03-12 05:29:43 +08:00
|
|
|
APInt InSignBit = APInt::getBitsSet(BitWidth, InBits - 1, InBits);
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt NewBits = ~InMask & NewMask;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
|
|
|
if (NewBits == 0)
|
2009-02-03 08:47:48 +08:00
|
|
|
return TLO.CombineTo(Op,TLO.DAG.getNode(ISD::ANY_EXTEND, dl,
|
|
|
|
Op.getValueType(),
|
|
|
|
Op.getOperand(0)));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// Since some of the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
2008-02-27 08:25:32 +08:00
|
|
|
APInt InDemandedBits = InMask & NewMask;
|
2006-02-27 07:36:02 +08:00
|
|
|
InDemandedBits |= InSignBit;
|
2010-12-07 16:25:19 +08:00
|
|
|
InDemandedBits = InDemandedBits.trunc(InBits);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedBits, KnownZero,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-12-07 16:25:19 +08:00
|
|
|
KnownZero = KnownZero.zext(BitWidth);
|
|
|
|
KnownOne = KnownOne.zext(BitWidth);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If the sign bit is known zero, convert this to a zero extend.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (KnownZero.intersects(InSignBit))
|
2009-02-03 08:47:48 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ZERO_EXTEND, dl,
|
2010-11-23 11:31:01 +08:00
|
|
|
Op.getValueType(),
|
2006-02-27 07:36:02 +08:00
|
|
|
Op.getOperand(0)));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If the sign bit is known one, the top bits match.
|
2008-02-27 08:25:32 +08:00
|
|
|
if (KnownOne.intersects(InSignBit)) {
|
2012-04-04 20:51:34 +08:00
|
|
|
KnownOne |= NewBits;
|
|
|
|
assert((KnownZero & NewBits) == 0);
|
2006-02-27 07:36:02 +08:00
|
|
|
} else { // Otherwise, top bits aren't known.
|
2012-04-04 20:51:34 +08:00
|
|
|
assert((KnownOne & NewBits) == 0);
|
|
|
|
assert((KnownZero & NewBits) == 0);
|
2006-02-27 07:36:02 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::ANY_EXTEND: {
|
2010-01-09 10:13:55 +08:00
|
|
|
unsigned OperandBitWidth =
|
|
|
|
Op.getOperand(0).getValueType().getScalarType().getSizeInBits();
|
2010-12-07 16:25:19 +08:00
|
|
|
APInt InMask = NewMask.trunc(OperandBitWidth);
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InMask,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2010-12-07 16:25:19 +08:00
|
|
|
KnownZero = KnownZero.zext(BitWidth);
|
|
|
|
KnownOne = KnownOne.zext(BitWidth);
|
2006-02-27 07:36:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2006-05-06 06:32:12 +08:00
|
|
|
case ISD::TRUNCATE: {
|
2006-05-06 08:11:52 +08:00
|
|
|
// Simplify the input, using demanded bit information, and compute the known
|
|
|
|
// zero/one bits live out.
|
2010-03-02 01:59:21 +08:00
|
|
|
unsigned OperandBitWidth =
|
|
|
|
Op.getOperand(0).getValueType().getScalarType().getSizeInBits();
|
2010-12-07 16:25:19 +08:00
|
|
|
APInt TruncMask = NewMask.zext(OperandBitWidth);
|
2008-02-27 08:25:32 +08:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), TruncMask,
|
2006-05-06 06:32:12 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-12-07 16:25:19 +08:00
|
|
|
KnownZero = KnownZero.trunc(BitWidth);
|
|
|
|
KnownOne = KnownOne.trunc(BitWidth);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-05-06 08:11:52 +08:00
|
|
|
// If the input is only used by this truncate, see if we can shrink it based
|
|
|
|
// on the known demanded bits.
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Op.getOperand(0).getNode()->hasOneUse()) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue In = Op.getOperand(0);
|
2006-05-06 08:11:52 +08:00
|
|
|
switch (In.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::SRL:
|
|
|
|
// Shrink SRL by a constant if none of the high bits shifted in are
|
|
|
|
// demanded.
|
2010-04-17 14:13:15 +08:00
|
|
|
if (TLO.LegalTypes() &&
|
|
|
|
!isTypeDesirableForOp(ISD::SRL, Op.getValueType()))
|
|
|
|
// Do not turn (vt1 truncate (vt2 srl)) into (vt1 srl) if vt1 is
|
|
|
|
// undesirable.
|
|
|
|
break;
|
|
|
|
ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(In.getOperand(1));
|
|
|
|
if (!ShAmt)
|
|
|
|
break;
|
2011-04-14 07:22:23 +08:00
|
|
|
SDValue Shift = In.getOperand(1);
|
|
|
|
if (TLO.LegalTypes()) {
|
|
|
|
uint64_t ShVal = ShAmt->getZExtValue();
|
|
|
|
Shift =
|
|
|
|
TLO.DAG.getConstant(ShVal, getShiftAmountTy(Op.getValueType()));
|
|
|
|
}
|
|
|
|
|
2010-04-17 14:13:15 +08:00
|
|
|
APInt HighBits = APInt::getHighBitsSet(OperandBitWidth,
|
|
|
|
OperandBitWidth - BitWidth);
|
2010-12-07 16:25:19 +08:00
|
|
|
HighBits = HighBits.lshr(ShAmt->getZExtValue()).trunc(BitWidth);
|
2010-04-17 14:13:15 +08:00
|
|
|
|
|
|
|
if (ShAmt->getZExtValue() < BitWidth && !(HighBits & NewMask)) {
|
|
|
|
// None of the shifted in bits are needed. Add a truncate of the
|
|
|
|
// shift input, then shift it.
|
|
|
|
SDValue NewTrunc = TLO.DAG.getNode(ISD::TRUNCATE, dl,
|
2010-11-23 11:31:01 +08:00
|
|
|
Op.getValueType(),
|
2010-04-17 14:13:15 +08:00
|
|
|
In.getOperand(0));
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl,
|
|
|
|
Op.getValueType(),
|
2010-11-23 11:31:01 +08:00
|
|
|
NewTrunc,
|
2011-04-14 07:22:23 +08:00
|
|
|
Shift));
|
2006-05-06 08:11:52 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-05-06 06:32:12 +08:00
|
|
|
break;
|
|
|
|
}
|
2006-02-27 07:36:02 +08:00
|
|
|
case ISD::AssertZext: {
|
2011-09-03 08:26:49 +08:00
|
|
|
// AssertZext demands all of the high bits, plus any of the low bits
|
|
|
|
// demanded by its users.
|
|
|
|
EVT VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
|
|
|
APInt InMask = APInt::getLowBitsSet(BitWidth,
|
|
|
|
VT.getSizeInBits());
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), ~InMask | NewMask,
|
2006-02-27 07:36:02 +08:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2010-11-23 11:31:01 +08:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2010-06-04 04:21:33 +08:00
|
|
|
|
2008-02-27 08:25:32 +08:00
|
|
|
KnownZero |= ~InMask & NewMask;
|
2006-02-27 07:36:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
case ISD::BITCAST:
|
2011-06-07 00:44:31 +08:00
|
|
|
// If this is an FP->Int bitcast and if the sign bit is the only
|
|
|
|
// thing demanded, turn this into a FGETSIGN.
|
2011-12-15 10:07:20 +08:00
|
|
|
if (!TLO.LegalOperations() &&
|
|
|
|
!Op.getValueType().isVector() &&
|
2011-11-10 06:25:12 +08:00
|
|
|
!Op.getOperand(0).getValueType().isVector() &&
|
2011-06-12 22:56:55 +08:00
|
|
|
NewMask == APInt::getSignBit(Op.getValueType().getSizeInBits()) &&
|
|
|
|
Op.getOperand(0).getValueType().isFloatingPoint()) {
|
2011-06-07 00:44:31 +08:00
|
|
|
bool OpVTLegal = isOperationLegalOrCustom(ISD::FGETSIGN, Op.getValueType());
|
|
|
|
bool i32Legal = isOperationLegalOrCustom(ISD::FGETSIGN, MVT::i32);
|
|
|
|
if ((OpVTLegal || i32Legal) && Op.getValueType().isSimple()) {
|
|
|
|
EVT Ty = OpVTLegal ? Op.getValueType() : MVT::i32;
|
2007-12-23 05:35:38 +08:00
|
|
|
// Make a FGETSIGN + SHL to move the sign bit into the appropriate
|
|
|
|
// place. We expect the SHL to be eliminated by other optimizations.
|
2011-06-02 02:32:25 +08:00
|
|
|
SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, dl, Ty, Op.getOperand(0));
|
2011-06-07 00:44:31 +08:00
|
|
|
unsigned OpVTSizeInBits = Op.getValueType().getSizeInBits();
|
|
|
|
if (!OpVTLegal && OpVTSizeInBits > 32)
|
2011-06-02 02:32:25 +08:00
|
|
|
Sign = TLO.DAG.getNode(ISD::ZERO_EXTEND, dl, Op.getValueType(), Sign);
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned ShVal = Op.getValueType().getSizeInBits()-1;
|
2011-06-01 22:04:17 +08:00
|
|
|
SDValue ShAmt = TLO.DAG.getConstant(ShVal, Op.getValueType());
|
2011-05-20 02:48:20 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, dl,
|
|
|
|
Op.getValueType(),
|
2007-12-23 05:35:38 +08:00
|
|
|
Sign, ShAmt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
case ISD::ADD:
|
|
|
|
case ISD::MUL:
|
|
|
|
case ISD::SUB: {
|
|
|
|
// Add, Sub, and Mul don't demand any bits in positions beyond that
|
|
|
|
// of the highest bit demanded of them.
|
|
|
|
APInt LoMask = APInt::getLowBitsSet(BitWidth,
|
|
|
|
BitWidth - NewMask.countLeadingZeros());
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), LoMask, KnownZero2,
|
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), LoMask, KnownZero2,
|
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
// See if the operation should be performed at a smaller bit width.
|
2010-06-24 22:30:44 +08:00
|
|
|
if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl))
|
Implement support for using modeling implicit-zero-extension on x86-64
with SUBREG_TO_REG, teach SimpleRegisterCoalescing to coalesce
SUBREG_TO_REG instructions (which are similar to INSERT_SUBREG
instructions), and teach the DAGCombiner to take advantage of this on
targets which support it. This eliminates many redundant
zero-extension operations on x86-64.
This adds a new TargetLowering hook, isZExtFree. It's similar to
isTruncateFree, except it only applies to actual definitions, and not
no-op truncates which may not zero the high bits.
Also, this adds a new optimization to SimplifyDemandedBits: transform
operations like x+y into (zext (add (trunc x), (trunc y))) on targets
where all the casts are no-ops. In contexts where the high part of the
add is explicitly masked off, this allows the mask operation to be
eliminated. Fix the DAGCombiner to avoid undoing these transformations
to eliminate casts on targets where the casts are no-ops.
Also, this adds a new two-address lowering heuristic. Since
two-address lowering runs before coalescing, it helps to be able to
look through copies when deciding whether commuting and/or
three-address conversion are profitable.
Also, fix a bug in LiveInterval::MergeInClobberRanges. It didn't handle
the case that a clobber range extended both before and beyond an
existing live range. In that case, multiple live ranges need to be
added. This was exposed by the new subreg coalescing code.
Remove 2008-05-06-SpillerBug.ll. It was bugpoint-reduced, and the
spiller behavior it was looking for no longer occurrs with the new
instruction selection.
llvm-svn: 68576
2009-04-08 08:15:30 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// FALL THROUGH
|
2008-05-06 08:53:29 +08:00
|
|
|
default:
|
2006-04-02 14:15:09 +08:00
|
|
|
// Just use ComputeMaskedBits to compute output bits.
|
2012-04-04 20:51:34 +08:00
|
|
|
TLO.DAG.ComputeMaskedBits(Op, KnownZero, KnownOne, Depth);
|
2006-02-27 09:00:42 +08:00
|
|
|
break;
|
2006-02-04 06:24:05 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-27 07:36:02 +08:00
|
|
|
// If we know the value of all of the demanded bits, return this as a
|
|
|
|
// constant.
|
2008-02-27 08:25:32 +08:00
|
|
|
if ((NewMask & (KnownZero|KnownOne)) == NewMask)
|
2006-02-27 07:36:02 +08:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType()));
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-02-04 06:24:05 +08:00
|
|
|
return false;
|
|
|
|
}
|
2006-01-30 12:09:27 +08:00
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
/// computeMaskedBitsForTargetNode - Determine which of the bits specified
|
|
|
|
/// in Mask are known to be either zero or one and return them in the
|
2006-02-17 05:11:51 +08:00
|
|
|
/// KnownZero/KnownOne bitsets.
|
2010-11-23 11:31:01 +08:00
|
|
|
void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
|
|
|
APInt &KnownZero,
|
2008-02-13 08:35:47 +08:00
|
|
|
APInt &KnownOne,
|
2007-06-22 22:59:07 +08:00
|
|
|
const SelectionDAG &DAG,
|
2006-02-17 05:11:51 +08:00
|
|
|
unsigned Depth) const {
|
2006-04-02 14:19:46 +08: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 12:09:27 +08:00
|
|
|
"Should use MaskedValueIsZero if you don't know whether Op"
|
|
|
|
" is a target node!");
|
2012-04-04 20:51:34 +08:00
|
|
|
KnownZero = KnownOne = APInt(KnownOne.getBitWidth(), 0);
|
2005-12-22 07:05:39 +08:00
|
|
|
}
|
2006-01-27 04:37:03 +08:00
|
|
|
|
2006-05-06 17:27:13 +08:00
|
|
|
/// ComputeNumSignBitsForTargetNode - This method can be implemented by
|
|
|
|
/// targets that want to expose additional information about sign bits to the
|
|
|
|
/// DAG Combiner.
|
2008-07-28 05:46:04 +08:00
|
|
|
unsigned TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
|
2006-05-06 17:27:13 +08: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;
|
|
|
|
}
|
|
|
|
|
2009-02-16 07:59:32 +08:00
|
|
|
/// ValueHasExactlyOneBitSet - Test if the given value is known to have exactly
|
|
|
|
/// one bit set. This differs from ComputeMaskedBits in that it doesn't need to
|
|
|
|
/// determine which bit is set.
|
|
|
|
///
|
2009-02-12 03:19:41 +08:00
|
|
|
static bool ValueHasExactlyOneBitSet(SDValue Val, const SelectionDAG &DAG) {
|
2009-02-16 07:59:32 +08:00
|
|
|
// A left-shift of a constant one will have exactly one bit set, because
|
|
|
|
// shifting the bit off the end is undefined.
|
|
|
|
if (Val.getOpcode() == ISD::SHL)
|
|
|
|
if (ConstantSDNode *C =
|
|
|
|
dyn_cast<ConstantSDNode>(Val.getNode()->getOperand(0)))
|
|
|
|
if (C->getAPIntValue() == 1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Similarly, a right-shift of a constant sign-bit will have exactly
|
|
|
|
// one bit set.
|
|
|
|
if (Val.getOpcode() == ISD::SRL)
|
|
|
|
if (ConstantSDNode *C =
|
|
|
|
dyn_cast<ConstantSDNode>(Val.getNode()->getOperand(0)))
|
|
|
|
if (C->getAPIntValue().isSignBit())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// More could be done here, though the above checks are enough
|
|
|
|
// to handle some common cases.
|
2009-01-29 09:59:02 +08:00
|
|
|
|
2009-02-16 07:59:32 +08:00
|
|
|
// Fall back to ComputeMaskedBits to catch other known cases.
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT OpVT = Val.getValueType();
|
2010-03-02 10:14:38 +08:00
|
|
|
unsigned BitWidth = OpVT.getScalarType().getSizeInBits();
|
2009-01-29 09:59:02 +08:00
|
|
|
APInt KnownZero, KnownOne;
|
2012-04-04 20:51:34 +08:00
|
|
|
DAG.ComputeMaskedBits(Val, KnownZero, KnownOne);
|
2009-02-12 03:19:41 +08:00
|
|
|
return (KnownZero.countPopulation() == BitWidth - 1) &&
|
|
|
|
(KnownOne.countPopulation() == 1);
|
2009-01-29 09:59:02 +08:00
|
|
|
}
|
2006-05-06 17:27:13 +08:00
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
/// SimplifySetCC - Try to simplify a setcc built with the specified operands
|
2008-07-28 05:46:04 +08:00
|
|
|
/// and cc. If it is unable to simplify it, return a null SDValue.
|
|
|
|
SDValue
|
2009-08-11 06:56:29 +08:00
|
|
|
TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
|
2007-02-09 06:13:59 +08:00
|
|
|
ISD::CondCode Cond, bool foldBooleans,
|
2009-02-03 08:47:48 +08:00
|
|
|
DAGCombinerInfo &DCI, DebugLoc dl) const {
|
2007-02-09 06:13:59 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-04-15 13:18:47 +08:00
|
|
|
// Ensure that the constant occurs on the RHS, and fold constant
|
|
|
|
// comparisons.
|
|
|
|
if (isa<ConstantSDNode>(N0.getNode()))
|
2009-07-27 07:47:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N1, N0, ISD::getSetCCSwappedOperands(Cond));
|
2011-06-18 04:41:29 +08:00
|
|
|
|
2008-08-29 05:40:38 +08:00
|
|
|
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode())) {
|
2008-03-04 06:22:56 +08:00
|
|
|
const APInt &C1 = N1C->getAPIntValue();
|
2009-07-27 07:47:17 +08:00
|
|
|
|
|
|
|
// 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) {
|
2010-01-08 04:58:44 +08:00
|
|
|
const APInt &ShAmt
|
|
|
|
= cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
|
2009-07-27 07:47:17 +08:00
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
ShAmt == Log2_32(N0.getValueType().getSizeInBits())) {
|
|
|
|
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;
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
SDValue Zero = DAG.getConstant(0, N0.getValueType());
|
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0).getOperand(0),
|
|
|
|
Zero, Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
2008-11-07 09:28:02 +08:00
|
|
|
|
2011-01-17 20:04:57 +08:00
|
|
|
SDValue CTPOP = N0;
|
|
|
|
// Look through truncs that don't change the value of a ctpop.
|
|
|
|
if (N0.hasOneUse() && N0.getOpcode() == ISD::TRUNCATE)
|
|
|
|
CTPOP = N0.getOperand(0);
|
|
|
|
|
|
|
|
if (CTPOP.hasOneUse() && CTPOP.getOpcode() == ISD::CTPOP &&
|
2011-01-18 02:00:28 +08:00
|
|
|
(N0 == CTPOP || N0.getValueType().getSizeInBits() >
|
2011-01-17 20:04:57 +08:00
|
|
|
Log2_32_Ceil(CTPOP.getValueType().getSizeInBits()))) {
|
|
|
|
EVT CTVT = CTPOP.getValueType();
|
|
|
|
SDValue CTOp = CTPOP.getOperand(0);
|
|
|
|
|
|
|
|
// (ctpop x) u< 2 -> (x & x-1) == 0
|
|
|
|
// (ctpop x) u> 1 -> (x & x-1) != 0
|
|
|
|
if ((Cond == ISD::SETULT && C1 == 2) || (Cond == ISD::SETUGT && C1 == 1)){
|
|
|
|
SDValue Sub = DAG.getNode(ISD::SUB, dl, CTVT, CTOp,
|
|
|
|
DAG.getConstant(1, CTVT));
|
|
|
|
SDValue And = DAG.getNode(ISD::AND, dl, CTVT, CTOp, Sub);
|
|
|
|
ISD::CondCode CC = Cond == ISD::SETULT ? ISD::SETEQ : ISD::SETNE;
|
|
|
|
return DAG.getSetCC(dl, VT, And, DAG.getConstant(0, CTVT), CC);
|
|
|
|
}
|
|
|
|
|
2012-09-27 18:14:43 +08:00
|
|
|
// TODO: (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal.
|
2011-01-17 20:04:57 +08:00
|
|
|
}
|
|
|
|
|
2011-04-23 02:47:44 +08:00
|
|
|
// (zext x) == C --> x == (trunc C)
|
|
|
|
if (DCI.isBeforeLegalize() && N0->hasOneUse() &&
|
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
|
|
|
unsigned MinBits = N0.getValueSizeInBits();
|
|
|
|
SDValue PreZExt;
|
|
|
|
if (N0->getOpcode() == ISD::ZERO_EXTEND) {
|
|
|
|
// ZExt
|
|
|
|
MinBits = N0->getOperand(0).getValueSizeInBits();
|
|
|
|
PreZExt = N0->getOperand(0);
|
|
|
|
} else if (N0->getOpcode() == ISD::AND) {
|
|
|
|
// DAGCombine turns costly ZExts into ANDs
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N0->getOperand(1)))
|
|
|
|
if ((C->getAPIntValue()+1).isPowerOf2()) {
|
|
|
|
MinBits = C->getAPIntValue().countTrailingOnes();
|
|
|
|
PreZExt = N0->getOperand(0);
|
|
|
|
}
|
|
|
|
} else if (LoadSDNode *LN0 = dyn_cast<LoadSDNode>(N0)) {
|
|
|
|
// ZEXTLOAD
|
|
|
|
if (LN0->getExtensionType() == ISD::ZEXTLOAD) {
|
|
|
|
MinBits = LN0->getMemoryVT().getSizeInBits();
|
|
|
|
PreZExt = N0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-02 18:20:22 +08:00
|
|
|
// Make sure we're not losing bits from the constant.
|
2011-04-23 02:47:44 +08:00
|
|
|
if (MinBits < C1.getBitWidth() && MinBits > C1.getActiveBits()) {
|
|
|
|
EVT MinVT = EVT::getIntegerVT(*DAG.getContext(), MinBits);
|
|
|
|
if (isTypeDesirableForOp(ISD::SETCC, MinVT)) {
|
|
|
|
// Will get folded away.
|
|
|
|
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MinVT, PreZExt);
|
|
|
|
SDValue C = DAG.getConstant(C1.trunc(MinBits), MinVT);
|
|
|
|
return DAG.getSetCC(dl, VT, Trunc, C, Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-27 07:47:17 +08: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 &&
|
|
|
|
N0.getNode()->hasOneUse() &&
|
|
|
|
isa<LoadSDNode>(N0.getOperand(0)) &&
|
|
|
|
N0.getOperand(0).getNode()->hasOneUse() &&
|
|
|
|
isa<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
LoadSDNode *Lod = cast<LoadSDNode>(N0.getOperand(0));
|
2010-01-08 04:58:44 +08:00
|
|
|
APInt bestMask;
|
2009-07-27 07:47:17 +08:00
|
|
|
unsigned bestWidth = 0, bestOffset = 0;
|
2010-01-08 04:58:44 +08:00
|
|
|
if (!Lod->isVolatile() && Lod->isUnindexed()) {
|
2009-07-27 07:47:17 +08:00
|
|
|
unsigned origWidth = N0.getValueType().getSizeInBits();
|
2010-01-08 04:58:44 +08:00
|
|
|
unsigned maskWidth = origWidth;
|
2010-11-23 11:31:01 +08:00
|
|
|
// We can narrow (e.g.) 16-bit extending loads on 32-bit target to
|
2009-07-27 07:47:17 +08:00
|
|
|
// 8 bits, but have to be careful...
|
|
|
|
if (Lod->getExtensionType() != ISD::NON_EXTLOAD)
|
|
|
|
origWidth = Lod->getMemoryVT().getSizeInBits();
|
2010-01-08 04:58:44 +08:00
|
|
|
const APInt &Mask =
|
|
|
|
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
|
2009-07-27 07:47:17 +08:00
|
|
|
for (unsigned width = origWidth / 2; width>=8; width /= 2) {
|
2010-01-08 04:58:44 +08:00
|
|
|
APInt newMask = APInt::getLowBitsSet(maskWidth, width);
|
2009-07-27 07:47:17 +08:00
|
|
|
for (unsigned offset=0; offset<origWidth/width; offset++) {
|
|
|
|
if ((newMask & Mask) == Mask) {
|
|
|
|
if (!TD->isLittleEndian())
|
|
|
|
bestOffset = (origWidth/width - offset - 1) * (width/8);
|
|
|
|
else
|
|
|
|
bestOffset = (uint64_t)offset * (width/8);
|
2010-01-08 04:58:44 +08:00
|
|
|
bestMask = Mask.lshr(offset * (width/8) * 8);
|
2009-07-27 07:47:17 +08:00
|
|
|
bestWidth = width;
|
|
|
|
break;
|
2008-11-07 09:28:02 +08:00
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
newMask = newMask << width;
|
2008-11-07 09:28:02 +08:00
|
|
|
}
|
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
|
|
|
if (bestWidth) {
|
2011-04-14 12:12:47 +08:00
|
|
|
EVT newVT = EVT::getIntegerVT(*DAG.getContext(), bestWidth);
|
2009-07-27 07:47:17 +08:00
|
|
|
if (newVT.isRound()) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT PtrType = Lod->getOperand(1).getValueType();
|
2009-07-27 07:47:17 +08:00
|
|
|
SDValue Ptr = Lod->getBasePtr();
|
|
|
|
if (bestOffset != 0)
|
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, PtrType, Lod->getBasePtr(),
|
|
|
|
DAG.getConstant(bestOffset, PtrType));
|
|
|
|
unsigned NewAlign = MinAlign(Lod->getAlignment(), bestOffset);
|
|
|
|
SDValue NewLoad = DAG.getLoad(newVT, dl, Lod->getChain(), Ptr,
|
2010-09-22 00:36:31 +08:00
|
|
|
Lod->getPointerInfo().getWithOffset(bestOffset),
|
2011-11-09 02:42:53 +08:00
|
|
|
false, false, false, NewAlign);
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT,
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getNode(ISD::AND, dl, newVT, NewLoad,
|
2010-01-08 04:58:44 +08:00
|
|
|
DAG.getConstant(bestMask.trunc(bestWidth),
|
|
|
|
newVT)),
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getConstant(0LL, newVT), Cond);
|
2008-11-07 09:28:02 +08:00
|
|
|
}
|
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
2008-11-11 05:22:06 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
// If the LHS is a ZERO_EXTEND, perform the comparison on the input.
|
|
|
|
if (N0.getOpcode() == ISD::ZERO_EXTEND) {
|
|
|
|
unsigned InSize = N0.getOperand(0).getValueType().getSizeInBits();
|
2007-02-09 06:13:59 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
// If the comparison constant has bits in the upper part, the
|
|
|
|
// zero-extended value could never match.
|
|
|
|
if (C1.intersects(APInt::getHighBitsSet(C1.getBitWidth(),
|
|
|
|
C1.getBitWidth() - InSize))) {
|
2007-02-09 06:13:59 +08:00
|
|
|
switch (Cond) {
|
|
|
|
case ISD::SETUGT:
|
|
|
|
case ISD::SETUGE:
|
2009-07-27 07:47:17 +08:00
|
|
|
case ISD::SETEQ: return DAG.getConstant(0, VT);
|
2007-02-09 06:13:59 +08:00
|
|
|
case ISD::SETULT:
|
2009-07-27 07:47:17 +08:00
|
|
|
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.
|
|
|
|
return DAG.getConstant(C1.isNegative(), VT);
|
|
|
|
case ISD::SETLT:
|
|
|
|
case ISD::SETLE:
|
|
|
|
// True if the sign bit of C1 isn't set.
|
|
|
|
return DAG.getConstant(C1.isNonNegative(), VT);
|
2007-02-09 06:13:59 +08:00
|
|
|
default:
|
2009-07-27 07:47:17 +08:00
|
|
|
break;
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
|
|
|
|
// 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: {
|
2012-12-11 19:14:33 +08:00
|
|
|
EVT newVT = N0.getOperand(0).getValueType();
|
2009-07-27 07:47:17 +08:00
|
|
|
if (DCI.isBeforeLegalizeOps() ||
|
|
|
|
(isOperationLegal(ISD::SETCC, newVT) &&
|
2012-12-19 18:09:26 +08:00
|
|
|
getCondCodeAction(Cond, newVT.getSimpleVT())==Legal))
|
2009-07-27 07:47:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0),
|
2010-12-07 16:25:19 +08:00
|
|
|
DAG.getConstant(C1.trunc(InSize), newVT),
|
2009-07-27 07:47:17 +08:00
|
|
|
Cond);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break; // todo, be more careful with signed comparisons
|
|
|
|
}
|
|
|
|
} else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
|
2010-02-27 15:36:59 +08:00
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT ExtSrcTy = cast<VTSDNode>(N0.getOperand(1))->getVT();
|
2009-07-27 07:47:17 +08:00
|
|
|
unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits();
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT ExtDstTy = N0.getValueType();
|
2009-07-27 07:47:17 +08:00
|
|
|
unsigned ExtDstTyBits = ExtDstTy.getSizeInBits();
|
|
|
|
|
2010-07-30 14:44:31 +08:00
|
|
|
// If the constant doesn't fit into the number of bits for the source of
|
|
|
|
// the sign extension, it is impossible for both sides to be equal.
|
|
|
|
if (C1.getMinSignedBits() > ExtSrcTyBits)
|
2009-07-27 07:47:17 +08:00
|
|
|
return DAG.getConstant(Cond == ISD::SETNE, VT);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
SDValue ZextOp;
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT Op0Ty = N0.getOperand(0).getValueType();
|
2009-07-27 07:47:17 +08:00
|
|
|
if (Op0Ty == ExtSrcTy) {
|
|
|
|
ZextOp = N0.getOperand(0);
|
2007-02-09 06:13:59 +08:00
|
|
|
} else {
|
2009-07-27 07:47:17 +08:00
|
|
|
APInt Imm = APInt::getLowBitsSet(ExtDstTyBits, ExtSrcTyBits);
|
|
|
|
ZextOp = DAG.getNode(ISD::AND, dl, Op0Ty, N0.getOperand(0),
|
|
|
|
DAG.getConstant(Imm, Op0Ty));
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(ZextOp.getNode());
|
|
|
|
// Otherwise, make this a use of a zext.
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, ZextOp,
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getConstant(C1 & APInt::getLowBitsSet(
|
|
|
|
ExtDstTyBits,
|
2010-11-23 11:31:01 +08:00
|
|
|
ExtSrcTyBits),
|
2009-07-27 07:47:17 +08:00
|
|
|
ExtDstTy),
|
|
|
|
Cond);
|
|
|
|
} else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) &&
|
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
|
|
|
// SETCC (SETCC), [0|1], [EQ|NE] -> SETCC
|
2010-02-27 15:36:59 +08:00
|
|
|
if (N0.getOpcode() == ISD::SETCC &&
|
|
|
|
isTypeLegal(VT) && VT.bitsLE(N0.getValueType())) {
|
2010-01-08 04:58:44 +08:00
|
|
|
bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1);
|
2009-07-27 07:47:17 +08:00
|
|
|
if (TrueWhenTrue)
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getNode(ISD::TRUNCATE, dl, VT, N0);
|
2009-07-27 07:47:17 +08:00
|
|
|
// Invert the condition.
|
|
|
|
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
|
2010-11-23 11:31:01 +08:00
|
|
|
CC = ISD::getSetCCInverse(CC,
|
2009-07-27 07:47:17 +08:00
|
|
|
N0.getOperand(0).getValueType().isInteger());
|
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2010-02-27 15:36:59 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
if ((N0.getOpcode() == ISD::XOR ||
|
2010-11-23 11:31:01 +08:00
|
|
|
(N0.getOpcode() == ISD::AND &&
|
2009-07-27 07:47:17 +08:00
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR &&
|
|
|
|
N0.getOperand(1) == N0.getOperand(0).getOperand(1))) &&
|
|
|
|
isa<ConstantSDNode>(N0.getOperand(1)) &&
|
|
|
|
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue() == 1) {
|
|
|
|
// 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.
|
|
|
|
unsigned BitWidth = N0.getValueSizeInBits();
|
|
|
|
if (DAG.MaskedValueIsZero(N0,
|
|
|
|
APInt::getHighBitsSet(BitWidth,
|
|
|
|
BitWidth-1))) {
|
|
|
|
// Okay, get the un-inverted input value.
|
|
|
|
SDValue Val;
|
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
Val = N0.getOperand(0);
|
|
|
|
else {
|
2010-11-23 11:31:01 +08:00
|
|
|
assert(N0.getOpcode() == ISD::AND &&
|
2009-07-27 07:47:17 +08:00
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR);
|
|
|
|
// ((X^1)&1)^1 -> X & 1
|
|
|
|
Val = DAG.getNode(ISD::AND, dl, N0.getValueType(),
|
|
|
|
N0.getOperand(0).getOperand(0),
|
|
|
|
N0.getOperand(1));
|
|
|
|
}
|
2010-02-27 15:36:59 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, Val, N1,
|
|
|
|
Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
|
|
|
|
}
|
2010-02-27 15:36:59 +08:00
|
|
|
} else if (N1C->getAPIntValue() == 1 &&
|
|
|
|
(VT == MVT::i1 ||
|
2011-09-07 03:07:46 +08:00
|
|
|
getBooleanContents(false) == ZeroOrOneBooleanContent)) {
|
2010-02-27 15:36:59 +08:00
|
|
|
SDValue Op0 = N0;
|
|
|
|
if (Op0.getOpcode() == ISD::TRUNCATE)
|
|
|
|
Op0 = Op0.getOperand(0);
|
|
|
|
|
|
|
|
if ((Op0.getOpcode() == ISD::XOR) &&
|
|
|
|
Op0.getOperand(0).getOpcode() == ISD::SETCC &&
|
|
|
|
Op0.getOperand(1).getOpcode() == ISD::SETCC) {
|
|
|
|
// (xor (setcc), (setcc)) == / != 1 -> (setcc) != / == (setcc)
|
|
|
|
Cond = (Cond == ISD::SETEQ) ? ISD::SETNE : ISD::SETEQ;
|
|
|
|
return DAG.getSetCC(dl, VT, Op0.getOperand(0), Op0.getOperand(1),
|
|
|
|
Cond);
|
2012-12-19 14:12:28 +08:00
|
|
|
}
|
|
|
|
if (Op0.getOpcode() == ISD::AND &&
|
|
|
|
isa<ConstantSDNode>(Op0.getOperand(1)) &&
|
|
|
|
cast<ConstantSDNode>(Op0.getOperand(1))->getAPIntValue() == 1) {
|
2010-02-27 15:36:59 +08:00
|
|
|
// If this is (X&1) == / != 1, normalize it to (X&1) != / == 0.
|
2010-05-01 20:52:34 +08:00
|
|
|
if (Op0.getValueType().bitsGT(VT))
|
2010-02-27 15:36:59 +08:00
|
|
|
Op0 = DAG.getNode(ISD::AND, dl, VT,
|
|
|
|
DAG.getNode(ISD::TRUNCATE, dl, VT, Op0.getOperand(0)),
|
|
|
|
DAG.getConstant(1, VT));
|
2010-05-01 20:52:34 +08:00
|
|
|
else if (Op0.getValueType().bitsLT(VT))
|
|
|
|
Op0 = DAG.getNode(ISD::AND, dl, VT,
|
|
|
|
DAG.getNode(ISD::ANY_EXTEND, dl, VT, Op0.getOperand(0)),
|
|
|
|
DAG.getConstant(1, VT));
|
|
|
|
|
2010-02-27 15:36:59 +08:00
|
|
|
return DAG.getSetCC(dl, VT, Op0,
|
|
|
|
DAG.getConstant(0, Op0.getValueType()),
|
|
|
|
Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
|
|
|
|
}
|
2012-12-19 14:12:28 +08:00
|
|
|
if (Op0.getOpcode() == ISD::AssertZext &&
|
|
|
|
cast<VTSDNode>(Op0.getOperand(1))->getVT() == MVT::i1)
|
|
|
|
return DAG.getSetCC(dl, VT, Op0,
|
|
|
|
DAG.getConstant(0, Op0.getValueType()),
|
|
|
|
Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
APInt MinVal, MaxVal;
|
|
|
|
unsigned OperandBitSize = N1C->getValueType(0).getSizeInBits();
|
|
|
|
if (ISD::isSignedIntSetCC(Cond)) {
|
|
|
|
MinVal = APInt::getSignedMinValue(OperandBitSize);
|
|
|
|
MaxVal = APInt::getSignedMaxValue(OperandBitSize);
|
|
|
|
} else {
|
|
|
|
MinVal = APInt::getMinValue(OperandBitSize);
|
|
|
|
MaxVal = APInt::getMaxValue(OperandBitSize);
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
|
2009-07-27 07:47:17 +08: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
|
|
|
|
// X >= C0 --> X > (C0-1)
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0,
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getConstant(C1-1, N1.getValueType()),
|
|
|
|
(Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT);
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
|
2009-07-27 07:47:17 +08:00
|
|
|
if (Cond == ISD::SETLE || Cond == ISD::SETULE) {
|
|
|
|
if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true
|
|
|
|
// X <= C0 --> X < (C0+1)
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0,
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getConstant(C1+1, N1.getValueType()),
|
|
|
|
(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(dl, VT, N0, N1, ISD::SETNE);
|
|
|
|
// Canonicalize setlt X, Max --> setne X, Max
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MaxVal)
|
|
|
|
return DAG.getSetCC(dl, 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)
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0,
|
|
|
|
DAG.getConstant(MinVal, N0.getValueType()),
|
2009-07-27 07:47:17 +08:00
|
|
|
ISD::SETEQ);
|
|
|
|
// If we have setugt X, Max-1, turn it into seteq X, Max
|
2012-12-19 14:43:58 +08:00
|
|
|
if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1)
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0,
|
2009-07-27 07:47:17 +08:00
|
|
|
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
|
2010-11-23 11:31:01 +08:00
|
|
|
if (Cond == ISD::SETUGT &&
|
2009-07-27 07:47:17 +08:00
|
|
|
C1 == APInt::getSignedMaxValue(OperandBitSize))
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0,
|
2009-07-27 07:47:17 +08:00
|
|
|
DAG.getConstant(0, N1.getValueType()),
|
|
|
|
ISD::SETLT);
|
|
|
|
|
|
|
|
// 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(dl, VT, N0, ConstMinusOne, ISD::SETGT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fold bit comparisons when we can.
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
2010-01-07 03:38:29 +08:00
|
|
|
(VT == N0.getValueType() ||
|
|
|
|
(isTypeLegal(VT) && VT.bitsLE(N0.getValueType()))) &&
|
|
|
|
N0.getOpcode() == ISD::AND)
|
2009-07-27 07:47:17 +08:00
|
|
|
if (ConstantSDNode *AndRHS =
|
|
|
|
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
2012-08-17 23:54:21 +08:00
|
|
|
EVT ShiftTy = DCI.isBeforeLegalizeOps() ?
|
2011-02-26 05:41:48 +08:00
|
|
|
getPointerTy() : getShiftAmountTy(N0.getValueType());
|
2009-07-27 07:47:17 +08:00
|
|
|
if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if the AND RHS is a single bit.
|
2010-01-08 04:58:44 +08:00
|
|
|
if (AndRHS->getAPIntValue().isPowerOf2()) {
|
2010-01-07 03:38:29 +08:00
|
|
|
return DAG.getNode(ISD::TRUNCATE, dl, VT,
|
|
|
|
DAG.getNode(ISD::SRL, dl, N0.getValueType(), N0,
|
2010-01-08 04:58:44 +08:00
|
|
|
DAG.getConstant(AndRHS->getAPIntValue().logBase2(), ShiftTy)));
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
2010-01-08 04:58:44 +08:00
|
|
|
} else if (Cond == ISD::SETEQ && C1 == AndRHS->getAPIntValue()) {
|
2009-07-27 07:47:17 +08:00
|
|
|
// (X & 8) == 8 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if C1 is a single bit.
|
|
|
|
if (C1.isPowerOf2()) {
|
2010-01-07 03:38:29 +08:00
|
|
|
return DAG.getNode(ISD::TRUNCATE, dl, VT,
|
|
|
|
DAG.getNode(ISD::SRL, dl, N0.getValueType(), N0,
|
|
|
|
DAG.getConstant(C1.logBase2(), ShiftTy)));
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
2009-07-27 07:47:17 +08:00
|
|
|
}
|
2012-07-17 14:53:39 +08:00
|
|
|
|
2012-07-17 15:47:50 +08:00
|
|
|
if (C1.getMinSignedBits() <= 64 &&
|
|
|
|
!isLegalICmpImmediate(C1.getSExtValue())) {
|
2012-07-17 14:53:39 +08:00
|
|
|
// (X & -256) == 256 -> (X >> 8) == 1
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
N0.getOpcode() == ISD::AND && N0.hasOneUse()) {
|
|
|
|
if (ConstantSDNode *AndRHS =
|
|
|
|
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
const APInt &AndRHSC = AndRHS->getAPIntValue();
|
|
|
|
if ((-AndRHSC).isPowerOf2() && (AndRHSC & C1) == C1) {
|
|
|
|
unsigned ShiftBits = AndRHSC.countTrailingZeros();
|
2012-08-17 23:54:21 +08:00
|
|
|
EVT ShiftTy = DCI.isBeforeLegalizeOps() ?
|
2012-07-17 14:53:39 +08:00
|
|
|
getPointerTy() : getShiftAmountTy(N0.getValueType());
|
|
|
|
EVT CmpTy = N0.getValueType();
|
|
|
|
SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0.getOperand(0),
|
|
|
|
DAG.getConstant(ShiftBits, ShiftTy));
|
|
|
|
SDValue CmpRHS = DAG.getConstant(C1.lshr(ShiftBits), CmpTy);
|
|
|
|
return DAG.getSetCC(dl, VT, Shift, CmpRHS, Cond);
|
|
|
|
}
|
|
|
|
}
|
2012-07-17 16:31:11 +08:00
|
|
|
} else if (Cond == ISD::SETULT || Cond == ISD::SETUGE ||
|
|
|
|
Cond == ISD::SETULE || Cond == ISD::SETUGT) {
|
|
|
|
bool AdjOne = (Cond == ISD::SETULE || Cond == ISD::SETUGT);
|
|
|
|
// X < 0x100000000 -> (X >> 32) < 1
|
|
|
|
// X >= 0x100000000 -> (X >> 32) >= 1
|
|
|
|
// X <= 0x0ffffffff -> (X >> 32) < 1
|
|
|
|
// X > 0x0ffffffff -> (X >> 32) >= 1
|
|
|
|
unsigned ShiftBits;
|
|
|
|
APInt NewC = C1;
|
|
|
|
ISD::CondCode NewCond = Cond;
|
|
|
|
if (AdjOne) {
|
|
|
|
ShiftBits = C1.countTrailingOnes();
|
|
|
|
NewC = NewC + 1;
|
|
|
|
NewCond = (Cond == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE;
|
|
|
|
} else {
|
|
|
|
ShiftBits = C1.countTrailingZeros();
|
|
|
|
}
|
|
|
|
NewC = NewC.lshr(ShiftBits);
|
|
|
|
if (ShiftBits && isLegalICmpImmediate(NewC.getSExtValue())) {
|
2012-08-17 23:54:21 +08:00
|
|
|
EVT ShiftTy = DCI.isBeforeLegalizeOps() ?
|
2012-07-17 16:31:11 +08:00
|
|
|
getPointerTy() : getShiftAmountTy(N0.getValueType());
|
|
|
|
EVT CmpTy = N0.getValueType();
|
|
|
|
SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0,
|
|
|
|
DAG.getConstant(ShiftBits, ShiftTy));
|
|
|
|
SDValue CmpRHS = DAG.getConstant(NewC, CmpTy);
|
|
|
|
return DAG.getSetCC(dl, VT, Shift, CmpRHS, NewCond);
|
|
|
|
}
|
2012-07-17 14:53:39 +08:00
|
|
|
}
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
2008-08-29 05:40:38 +08:00
|
|
|
if (isa<ConstantFPSDNode>(N0.getNode())) {
|
2007-02-09 06:13:59 +08:00
|
|
|
// Constant fold or commute setcc.
|
2009-02-03 08:47:48 +08:00
|
|
|
SDValue O = DAG.FoldSetCC(VT, N0, N1, Cond, dl);
|
2008-08-29 05:40:38 +08: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
llvm-svn: 45405
2007-12-29 16:37:08 +08: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)) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Unknown flavor!");
|
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
llvm-svn: 45405
2007-12-29 16:37:08 +08:00
|
|
|
case 0: // Known false.
|
|
|
|
return DAG.getConstant(0, VT);
|
|
|
|
case 1: // Known true.
|
|
|
|
return DAG.getConstant(1, VT);
|
2007-12-31 05:21:10 +08:00
|
|
|
case 2: // Undefined.
|
2009-02-07 07:05:02 +08:00
|
|
|
return DAG.getUNDEF(VT);
|
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
llvm-svn: 45405
2007-12-29 16:37:08 +08:00
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
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
llvm-svn: 45405
2007-12-29 16:37:08 +08:00
|
|
|
// 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)
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N0, Cond);
|
2009-09-26 23:24:17 +08:00
|
|
|
|
|
|
|
// If the condition is not legal, see if we can find an equivalent one
|
|
|
|
// which is legal.
|
2012-12-19 18:19:55 +08:00
|
|
|
if (!isCondCodeLegal(Cond, N0.getSimpleValueType())) {
|
2009-09-26 23:24:17 +08:00
|
|
|
// If the comparison was an awkward floating-point == or != and one of
|
|
|
|
// the comparison operands is infinity or negative infinity, convert the
|
|
|
|
// condition to a less-awkward <= or >=.
|
|
|
|
if (CFP->getValueAPF().isInfinity()) {
|
|
|
|
if (CFP->getValueAPF().isNegative()) {
|
|
|
|
if (Cond == ISD::SETOEQ &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETOLE, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLE);
|
|
|
|
if (Cond == ISD::SETUEQ &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETOLE, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULE);
|
|
|
|
if (Cond == ISD::SETUNE &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETUGT, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGT);
|
|
|
|
if (Cond == ISD::SETONE &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETUGT, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGT);
|
|
|
|
} else {
|
|
|
|
if (Cond == ISD::SETOEQ &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETOGE, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGE);
|
|
|
|
if (Cond == ISD::SETUEQ &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETOGE, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGE);
|
|
|
|
if (Cond == ISD::SETUNE &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETULT, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULT);
|
|
|
|
if (Cond == ISD::SETONE &&
|
2012-12-19 18:19:55 +08:00
|
|
|
isCondCodeLegal(ISD::SETULT, N0.getSimpleValueType()))
|
2009-09-26 23:24:17 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (N0 == N1) {
|
2012-07-05 17:32:46 +08:00
|
|
|
// The sext(setcc()) => setcc() optimization relies on the appropriate
|
|
|
|
// constant being emitted.
|
2012-09-06 19:13:55 +08:00
|
|
|
uint64_t EqVal = 0;
|
2012-07-05 17:32:46 +08:00
|
|
|
switch (getBooleanContents(N0.getValueType().isVector())) {
|
|
|
|
case UndefinedBooleanContent:
|
|
|
|
case ZeroOrOneBooleanContent:
|
|
|
|
EqVal = ISD::isTrueWhenEqual(Cond);
|
|
|
|
break;
|
|
|
|
case ZeroOrNegativeOneBooleanContent:
|
|
|
|
EqVal = ISD::isTrueWhenEqual(Cond) ? -1 : 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-02-09 06:13:59 +08:00
|
|
|
// We can always fold X == X for integer setcc's.
|
2012-04-04 04:11:24 +08:00
|
|
|
if (N0.getValueType().isInteger()) {
|
2012-07-05 17:32:46 +08:00
|
|
|
return DAG.getConstant(EqVal, VT);
|
2012-04-04 04:11:24 +08:00
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
unsigned UOF = ISD::getUnorderedFlavor(Cond);
|
|
|
|
if (UOF == 2) // FP operators that are undefined on NaNs.
|
2012-07-05 17:32:46 +08:00
|
|
|
return DAG.getConstant(EqVal, VT);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (UOF == unsigned(ISD::isTrueWhenEqual(Cond)))
|
2012-07-05 17:32:46 +08:00
|
|
|
return DAG.getConstant(EqVal, VT);
|
2007-02-09 06:13:59 +08:00
|
|
|
// 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;
|
2012-08-01 02:07:43 +08:00
|
|
|
if (NewCond != Cond && (DCI.isBeforeLegalizeOps() ||
|
2012-12-19 18:09:26 +08:00
|
|
|
getCondCodeAction(NewCond, N0.getSimpleValueType()) == Legal))
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, N1, NewCond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
2008-06-06 20:08:01 +08:00
|
|
|
N0.getValueType().isInteger()) {
|
2007-02-09 06:13:59 +08: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))
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(1), Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (N0.getOperand(1) == N1.getOperand(1))
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(0), Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode())) {
|
|
|
|
// If X op Y == Y op X, try other combinations.
|
|
|
|
if (N0.getOperand(0) == N1.getOperand(1))
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(0),
|
2009-02-03 08:47:48 +08:00
|
|
|
Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (N0.getOperand(1) == N1.getOperand(0))
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(1),
|
2009-02-03 08:47:48 +08:00
|
|
|
Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2012-04-06 04:30:20 +08:00
|
|
|
// If RHS is a legal immediate value for a compare instruction, we need
|
|
|
|
// to be careful about increasing register pressure needlessly.
|
|
|
|
bool LegalRHSImm = false;
|
|
|
|
|
2007-02-09 06:13:59 +08:00
|
|
|
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-29 05:40:38 +08:00
|
|
|
if (N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse()) {
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0),
|
2008-09-13 00:56:44 +08:00
|
|
|
DAG.getConstant(RHSC->getAPIntValue()-
|
|
|
|
LHSR->getAPIntValue(),
|
2007-02-09 06:13:59 +08:00
|
|
|
N0.getValueType()), Cond);
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2012-09-27 18:14:43 +08:00
|
|
|
// Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0.
|
2007-02-09 06:13:59 +08:00
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
// If we know that all of the inverted bits are zero, don't bother
|
|
|
|
// performing the inversion.
|
2008-02-26 05:11:39 +08:00
|
|
|
if (DAG.MaskedValueIsZero(N0.getOperand(0), ~LHSR->getAPIntValue()))
|
|
|
|
return
|
2009-02-03 08:47:48 +08:00
|
|
|
DAG.getSetCC(dl, VT, N0.getOperand(0),
|
2008-02-26 05:11:39 +08:00
|
|
|
DAG.getConstant(LHSR->getAPIntValue() ^
|
|
|
|
RHSC->getAPIntValue(),
|
|
|
|
N0.getValueType()),
|
|
|
|
Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-02-09 06:13:59 +08:00
|
|
|
// Turn (C1-X) == C2 --> X == C1-C2
|
|
|
|
if (ConstantSDNode *SUBC = dyn_cast<ConstantSDNode>(N0.getOperand(0))) {
|
2008-08-29 05:40:38 +08:00
|
|
|
if (N0.getOpcode() == ISD::SUB && N0.getNode()->hasOneUse()) {
|
2008-02-26 05:11:39 +08:00
|
|
|
return
|
2009-02-03 08:47:48 +08:00
|
|
|
DAG.getSetCC(dl, VT, N0.getOperand(1),
|
2008-02-26 05:11:39 +08:00
|
|
|
DAG.getConstant(SUBC->getAPIntValue() -
|
|
|
|
RHSC->getAPIntValue(),
|
|
|
|
N0.getValueType()),
|
|
|
|
Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
}
|
2012-04-06 04:30:20 +08:00
|
|
|
|
|
|
|
// Could RHSC fold directly into a compare?
|
|
|
|
if (RHSC->getValueType(0).getSizeInBits() <= 64)
|
|
|
|
LegalRHSImm = isLegalICmpImmediate(RHSC->getSExtValue());
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Simplify (X+Z) == X --> Z == 0
|
2012-04-06 04:30:20 +08:00
|
|
|
// Don't do this if X is an immediate that can fold into a cmp
|
|
|
|
// instruction and X+Z has other uses. It could be an induction variable
|
|
|
|
// chain, and the transform would increase register pressure.
|
|
|
|
if (!LegalRHSImm || N0.getNode()->hasOneUse()) {
|
|
|
|
if (N0.getOperand(0) == N1)
|
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(1),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
|
|
|
if (N0.getOperand(1) == N1) {
|
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode()))
|
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
2012-12-19 14:43:58 +08:00
|
|
|
if (N0.getNode()->hasOneUse()) {
|
2012-04-06 04:30:20 +08:00
|
|
|
assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// (Z-X) == X --> Z == X<<1
|
|
|
|
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N1,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(1, getShiftAmountTy(N1.getValueType())));
|
2012-04-06 04:30:20 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(SH.getNode());
|
|
|
|
return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond);
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB ||
|
|
|
|
N1.getOpcode() == ISD::XOR) {
|
|
|
|
// Simplify X == (X+Z) --> Z == 0
|
2012-12-19 14:43:58 +08:00
|
|
|
if (N1.getOperand(0) == N0)
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N1.getOperand(1),
|
2007-02-09 06:13:59 +08:00
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
2012-12-19 14:43:58 +08:00
|
|
|
if (N1.getOperand(1) == N0) {
|
|
|
|
if (DAG.isCommutativeBinOp(N1.getOpcode()))
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N1.getOperand(0),
|
2007-02-09 06:13:59 +08:00
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
2012-12-19 14:43:58 +08:00
|
|
|
if (N1.getNode()->hasOneUse()) {
|
2007-02-09 06:13:59 +08:00
|
|
|
assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// X == (Z-X) --> X<<1 == Z
|
2010-11-23 11:31:01 +08:00
|
|
|
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(1, getShiftAmountTy(N0.getValueType())));
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(SH.getNode());
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-29 09:59:02 +08:00
|
|
|
|
2009-01-30 00:18:12 +08:00
|
|
|
// Simplify x&y == y to x&y != 0 if y has exactly one bit set.
|
2009-02-12 03:19:41 +08:00
|
|
|
// Note that where y is variable and is known to have at most
|
|
|
|
// one bit set (for example, if it is z&1) we cannot do this;
|
|
|
|
// the expressions are not equivalent when y==0.
|
2009-01-29 09:59:02 +08:00
|
|
|
if (N0.getOpcode() == ISD::AND)
|
|
|
|
if (N0.getOperand(0) == N1 || N0.getOperand(1) == N1) {
|
2009-02-12 03:19:41 +08:00
|
|
|
if (ValueHasExactlyOneBitSet(N1, DAG)) {
|
2009-01-29 09:59:02 +08:00
|
|
|
Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true);
|
|
|
|
SDValue Zero = DAG.getConstant(0, N1.getValueType());
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N0, Zero, Cond);
|
2009-01-29 09:59:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (N1.getOpcode() == ISD::AND)
|
|
|
|
if (N1.getOperand(0) == N0 || N1.getOperand(1) == N0) {
|
2009-02-12 03:19:41 +08:00
|
|
|
if (ValueHasExactlyOneBitSet(N0, DAG)) {
|
2009-01-29 09:59:02 +08:00
|
|
|
Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true);
|
|
|
|
SDValue Zero = DAG.getConstant(0, N0.getValueType());
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getSetCC(dl, VT, N1, Zero, Cond);
|
2009-01-29 09:59:02 +08:00
|
|
|
}
|
|
|
|
}
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fold away ALL boolean setcc's.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Temp;
|
2009-08-12 04:47:22 +08:00
|
|
|
if (N0.getValueType() == MVT::i1 && foldBooleans) {
|
2007-02-09 06:13:59 +08:00
|
|
|
switch (Cond) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Unknown integer setcc!");
|
2009-01-23 01:39:32 +08:00
|
|
|
case ISD::SETEQ: // X == Y -> ~(X^Y)
|
2009-08-12 04:47:22 +08:00
|
|
|
Temp = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1);
|
|
|
|
N0 = DAG.getNOT(dl, Temp, MVT::i1);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
|
|
|
case ISD::SETNE: // X != Y --> (X^Y)
|
2009-08-12 04:47:22 +08:00
|
|
|
N0 = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1);
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
2009-01-23 01:39:32 +08:00
|
|
|
case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> ~X & Y
|
|
|
|
case ISD::SETULT: // X <u Y --> X == 0 & Y == 1 --> ~X & Y
|
2009-08-12 04:47:22 +08:00
|
|
|
Temp = DAG.getNOT(dl, N0, MVT::i1);
|
|
|
|
N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N1, Temp);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
2009-01-23 01:39:32 +08:00
|
|
|
case ISD::SETLT: // X <s Y --> X == 1 & Y == 0 --> ~Y & X
|
|
|
|
case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> ~Y & X
|
2009-08-12 04:47:22 +08:00
|
|
|
Temp = DAG.getNOT(dl, N1, MVT::i1);
|
|
|
|
N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N0, Temp);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
2009-01-23 01:39:32 +08:00
|
|
|
case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> ~X | Y
|
|
|
|
case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> ~X | Y
|
2009-08-12 04:47:22 +08:00
|
|
|
Temp = DAG.getNOT(dl, N0, MVT::i1);
|
|
|
|
N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N1, Temp);
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(Temp.getNode());
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
2009-01-23 01:39:32 +08:00
|
|
|
case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> ~Y | X
|
|
|
|
case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> ~Y | X
|
2009-08-12 04:47:22 +08:00
|
|
|
Temp = DAG.getNOT(dl, N1, MVT::i1);
|
|
|
|
N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N0, Temp);
|
2007-02-09 06:13:59 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-08-12 04:47:22 +08:00
|
|
|
if (VT != MVT::i1) {
|
2007-02-09 06:13:59 +08:00
|
|
|
if (!DCI.isCalledByLegalizer())
|
2008-08-29 05:40:38 +08:00
|
|
|
DCI.AddToWorklist(N0.getNode());
|
2007-02-09 06:13:59 +08:00
|
|
|
// FIXME: If running after legalize, we probably can't do this.
|
2009-02-03 08:47:48 +08:00
|
|
|
N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0);
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
return N0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Could not fold it.
|
2008-07-28 05:46:04 +08:00
|
|
|
return SDValue();
|
2007-02-09 06:13:59 +08:00
|
|
|
}
|
|
|
|
|
2008-05-13 03:56:52 +08:00
|
|
|
/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the
|
|
|
|
/// node is a GlobalAddress + offset.
|
2011-02-14 06:25:43 +08:00
|
|
|
bool TargetLowering::isGAPlusOffset(SDNode *N, const GlobalValue *&GA,
|
2008-05-13 03:56:52 +08:00
|
|
|
int64_t &Offset) const {
|
|
|
|
if (isa<GlobalAddressSDNode>(N)) {
|
2008-06-10 06:05:52 +08:00
|
|
|
GlobalAddressSDNode *GASD = cast<GlobalAddressSDNode>(N);
|
|
|
|
GA = GASD->getGlobal();
|
|
|
|
Offset += GASD->getOffset();
|
2008-05-13 03:56:52 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N->getOpcode() == ISD::ADD) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue N1 = N->getOperand(0);
|
|
|
|
SDValue N2 = N->getOperand(1);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (isGAPlusOffset(N1.getNode(), GA, Offset)) {
|
2008-05-13 03:56:52 +08:00
|
|
|
ConstantSDNode *V = dyn_cast<ConstantSDNode>(N2);
|
|
|
|
if (V) {
|
2008-09-27 05:54:37 +08:00
|
|
|
Offset += V->getSExtValue();
|
2008-05-13 03:56:52 +08:00
|
|
|
return true;
|
|
|
|
}
|
2008-08-29 05:40:38 +08:00
|
|
|
} else if (isGAPlusOffset(N2.getNode(), GA, Offset)) {
|
2008-05-13 03:56:52 +08:00
|
|
|
ConstantSDNode *V = dyn_cast<ConstantSDNode>(N1);
|
|
|
|
if (V) {
|
2008-09-27 05:54:37 +08:00
|
|
|
Offset += V->getSExtValue();
|
2008-05-13 03:56:52 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-26 05:41:48 +08:00
|
|
|
|
2008-05-13 03:56:52 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue TargetLowering::
|
2006-03-01 12:52:55 +08:00
|
|
|
PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
|
|
|
// Default implementation: no optimization.
|
2008-07-28 05:46:04 +08:00
|
|
|
return SDValue();
|
2006-03-01 12:52:55 +08:00
|
|
|
}
|
|
|
|
|
2006-02-04 10:13:02 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Inline Assembler Implementation Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
|
2006-02-04 10:13:02 +08:00
|
|
|
TargetLowering::ConstraintType
|
2007-03-25 10:14:49 +08:00
|
|
|
TargetLowering::getConstraintType(const std::string &Constraint) const {
|
|
|
|
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
|
2010-09-22 06:04:54 +08:00
|
|
|
case 'E': // Floating Point Constant
|
|
|
|
case 'F': // Floating Point Constant
|
2007-03-25 10:14:49 +08:00
|
|
|
case 's': // Relocatable Constant
|
2010-09-22 06:04:54 +08:00
|
|
|
case 'p': // Address.
|
2007-03-25 12:35:41 +08:00
|
|
|
case 'X': // Allow ANY value.
|
2007-03-25 10:14:49 +08:00
|
|
|
case 'I': // Target registers.
|
|
|
|
case 'J':
|
|
|
|
case 'K':
|
|
|
|
case 'L':
|
|
|
|
case 'M':
|
|
|
|
case 'N':
|
|
|
|
case 'O':
|
|
|
|
case 'P':
|
2010-09-22 06:04:54 +08:00
|
|
|
case '<':
|
|
|
|
case '>':
|
2007-03-25 10:14:49 +08:00
|
|
|
return C_Other;
|
|
|
|
}
|
2006-02-04 10:13:02 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
if (Constraint.size() > 1 && Constraint[0] == '{' &&
|
2007-03-25 10:18:14 +08:00
|
|
|
Constraint[Constraint.size()-1] == '}')
|
|
|
|
return C_Register;
|
2007-03-25 10:14:49 +08:00
|
|
|
return C_Unknown;
|
2006-02-04 10:13:02 +08:00
|
|
|
}
|
|
|
|
|
2008-01-29 10:21:21 +08: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.
|
2009-08-11 06:56:29 +08:00
|
|
|
const char *TargetLowering::LowerXConstraint(EVT ConstraintVT) const{
|
2008-06-06 20:08:01 +08:00
|
|
|
if (ConstraintVT.isInteger())
|
2008-04-27 07:02:14 +08:00
|
|
|
return "r";
|
2008-06-06 20:08:01 +08:00
|
|
|
if (ConstraintVT.isFloatingPoint())
|
2008-04-27 07:02:14 +08:00
|
|
|
return "f"; // works for many targets
|
|
|
|
return 0;
|
2008-01-29 10:21:21 +08:00
|
|
|
}
|
|
|
|
|
2007-08-25 08:47:38 +08:00
|
|
|
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
|
|
|
|
/// vector. If it is invalid, don't add anything to Ops.
|
2008-07-28 05:46:04 +08:00
|
|
|
void TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
|
2011-06-03 07:16:42 +08:00
|
|
|
std::string &Constraint,
|
2008-07-28 05:46:04 +08:00
|
|
|
std::vector<SDValue> &Ops,
|
2008-04-27 07:02:14 +08:00
|
|
|
SelectionDAG &DAG) const {
|
2011-06-18 04:41:29 +08:00
|
|
|
|
2011-06-03 07:16:42 +08:00
|
|
|
if (Constraint.length() > 1) return;
|
2011-06-18 04:41:29 +08:00
|
|
|
|
2011-06-03 07:16:42 +08:00
|
|
|
char ConstraintLetter = Constraint[0];
|
2006-02-04 10:13:02 +08:00
|
|
|
switch (ConstraintLetter) {
|
2007-02-17 14:00:35 +08:00
|
|
|
default: break;
|
2007-11-06 05:20:28 +08: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 10:13:02 +08:00
|
|
|
case 'i': // Simple Integer or Relocatable Constant
|
|
|
|
case 'n': // Simple Integer
|
2007-11-06 05:20:28 +08:00
|
|
|
case 's': { // Relocatable Constant
|
2007-05-04 00:54:34 +08: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);
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-05-04 00:54:34 +08:00
|
|
|
// 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;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-05-04 00:54:34 +08:00
|
|
|
// 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-13 00:56:44 +08:00
|
|
|
if (C) Offs += C->getZExtValue();
|
2010-11-23 11:31:01 +08:00
|
|
|
Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(),
|
2010-07-16 02:45:27 +08:00
|
|
|
C ? C->getDebugLoc() : DebugLoc(),
|
2007-08-25 08:47:38 +08:00
|
|
|
Op.getValueType(), Offs));
|
|
|
|
return;
|
2007-05-04 00:54:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (C) { // just C, no GV.
|
2007-02-17 14:00:35 +08:00
|
|
|
// Simple constants are not allowed for 's'.
|
2007-08-25 08:47:38 +08:00
|
|
|
if (ConstraintLetter != 's') {
|
2009-02-13 04:58:09 +08:00
|
|
|
// gcc prints these as sign extended. Sign extend value to 64 bits
|
|
|
|
// now; without this it would get ZExt'd later in
|
|
|
|
// ScheduleDAGSDNodes::EmitNode, which is very generic.
|
|
|
|
Ops.push_back(DAG.getTargetConstant(C->getAPIntValue().getSExtValue(),
|
2009-08-12 04:47:22 +08:00
|
|
|
MVT::i64));
|
2007-08-25 08:47:38 +08:00
|
|
|
return;
|
|
|
|
}
|
2007-02-17 14:00:35 +08:00
|
|
|
}
|
|
|
|
break;
|
2006-02-04 10:13:02 +08:00
|
|
|
}
|
2007-05-04 00:54:34 +08:00
|
|
|
}
|
2006-02-04 10:13:02 +08:00
|
|
|
}
|
|
|
|
|
2006-02-22 08:56:39 +08:00
|
|
|
std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
|
2006-02-22 07:11:00 +08:00
|
|
|
getRegForInlineAsmConstraint(const std::string &Constraint,
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT) const {
|
2006-02-22 08:56:39 +08:00
|
|
|
if (Constraint[0] != '{')
|
2010-05-11 14:17:44 +08:00
|
|
|
return std::make_pair(0u, static_cast<TargetRegisterClass*>(0));
|
2006-02-01 09:29:47 +08:00
|
|
|
assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
|
|
|
|
|
|
|
|
// Remove the braces from around the name.
|
2009-11-13 04:36:59 +08:00
|
|
|
StringRef RegName(Constraint.data()+1, Constraint.size()-2);
|
2006-02-22 08:56:39 +08:00
|
|
|
|
2012-12-19 01:50:58 +08:00
|
|
|
std::pair<unsigned, const TargetRegisterClass*> R =
|
|
|
|
std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
|
|
|
|
|
2006-02-22 08:56:39 +08:00
|
|
|
// Figure out which register class contains this reg.
|
2008-02-11 02:45:23 +08:00
|
|
|
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
|
|
|
for (TargetRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
|
2006-02-22 08:56:39 +08:00
|
|
|
E = RI->regclass_end(); RCI != E; ++RCI) {
|
|
|
|
const TargetRegisterClass *RC = *RCI;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
// If none of the value types for this register class are valid, we
|
2006-02-23 07:00:51 +08:00
|
|
|
// can't use it. For example, 64-bit reg classes on 32-bit targets.
|
2011-10-12 09:24:51 +08:00
|
|
|
if (!isLegalRC(RC))
|
|
|
|
continue;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
|
2006-02-22 08:56:39 +08:00
|
|
|
I != E; ++I) {
|
2012-12-19 01:50:58 +08:00
|
|
|
if (RegName.equals_lower(RI->getName(*I))) {
|
|
|
|
std::pair<unsigned, const TargetRegisterClass*> S =
|
|
|
|
std::make_pair(*I, RC);
|
|
|
|
|
|
|
|
// If this register class has the requested value type, return it,
|
|
|
|
// otherwise keep searching and return the first class found
|
|
|
|
// if no other is found which explicitly has the requested type.
|
|
|
|
if (RC->hasType(VT))
|
|
|
|
return S;
|
|
|
|
else if (!R.second)
|
|
|
|
R = S;
|
|
|
|
}
|
2006-02-22 08:56:39 +08:00
|
|
|
}
|
2006-01-27 04:37:03 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2012-12-19 01:50:58 +08:00
|
|
|
return R;
|
2006-01-27 04:37:03 +08:00
|
|
|
}
|
2006-03-14 07:18:16 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Constraint Selection.
|
|
|
|
|
2008-10-18 00:47:46 +08:00
|
|
|
/// isMatchingInputConstraint - Return true of this is an input operand that is
|
|
|
|
/// a matching constraint like "4".
|
|
|
|
bool TargetLowering::AsmOperandInfo::isMatchingInputConstraint() const {
|
2008-10-18 00:21:11 +08: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());
|
|
|
|
}
|
|
|
|
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-09-14 02:15:37 +08:00
|
|
|
/// ParseConstraints - Split up the constraint string from the inline
|
|
|
|
/// assembly value into the specific constraints and their prefixes,
|
|
|
|
/// and also tie in the associated operand values.
|
|
|
|
/// If this returns an empty vector, and if the constraint string itself
|
|
|
|
/// isn't empty, there was an error parsing.
|
2010-10-30 01:29:13 +08:00
|
|
|
TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints(
|
2010-09-14 02:15:37 +08:00
|
|
|
ImmutableCallSite CS) const {
|
|
|
|
/// ConstraintOperands - Information about all of the constraints.
|
2010-10-30 01:29:13 +08:00
|
|
|
AsmOperandInfoVector ConstraintOperands;
|
2010-09-14 02:15:37 +08:00
|
|
|
const InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
|
2010-09-22 06:04:54 +08:00
|
|
|
unsigned maCount = 0; // Largest number of multiple alternative constraints.
|
2010-09-14 02:15:37 +08:00
|
|
|
|
|
|
|
// Do a prepass over the constraints, canonicalizing them, and building up the
|
|
|
|
// ConstraintOperands list.
|
2010-10-30 01:29:13 +08:00
|
|
|
InlineAsm::ConstraintInfoVector
|
2010-09-14 02:15:37 +08:00
|
|
|
ConstraintInfos = IA->ParseConstraints();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-09-14 02:15:37 +08:00
|
|
|
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
|
|
|
unsigned ResNo = 0; // ResNo - The result number of the next output.
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
|
|
|
ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
|
|
|
|
AsmOperandInfo &OpInfo = ConstraintOperands.back();
|
|
|
|
|
2010-09-22 06:04:54 +08:00
|
|
|
// Update multiple alternative constraint count.
|
|
|
|
if (OpInfo.multipleAlternatives.size() > maCount)
|
|
|
|
maCount = OpInfo.multipleAlternatives.size();
|
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
OpInfo.ConstraintVT = MVT::Other;
|
2010-09-14 02:15:37 +08:00
|
|
|
|
|
|
|
// Compute the value type for each operand.
|
|
|
|
switch (OpInfo.Type) {
|
|
|
|
case InlineAsm::isOutput:
|
|
|
|
// Indirect outputs just consume an argument.
|
|
|
|
if (OpInfo.isIndirect) {
|
|
|
|
OpInfo.CallOperandVal = const_cast<Value *>(CS.getArgument(ArgNo++));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The return value of the call is this value. As such, there is no
|
|
|
|
// corresponding argument.
|
|
|
|
assert(!CS.getType()->isVoidTy() &&
|
|
|
|
"Bad inline asm!");
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *STy = dyn_cast<StructType>(CS.getType())) {
|
2012-12-19 23:19:11 +08:00
|
|
|
OpInfo.ConstraintVT = getSimpleValueType(STy->getElementType(ResNo));
|
2010-09-14 02:15:37 +08:00
|
|
|
} else {
|
|
|
|
assert(ResNo == 0 && "Asm only has one result!");
|
2012-12-19 23:19:11 +08:00
|
|
|
OpInfo.ConstraintVT = getSimpleValueType(CS.getType());
|
2010-09-14 02:15:37 +08:00
|
|
|
}
|
|
|
|
++ResNo;
|
|
|
|
break;
|
|
|
|
case InlineAsm::isInput:
|
|
|
|
OpInfo.CallOperandVal = const_cast<Value *>(CS.getArgument(ArgNo++));
|
|
|
|
break;
|
|
|
|
case InlineAsm::isClobber:
|
|
|
|
// Nothing to do.
|
|
|
|
break;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
if (OpInfo.CallOperandVal) {
|
2011-07-18 12:54:35 +08:00
|
|
|
llvm::Type *OpTy = OpInfo.CallOperandVal->getType();
|
2010-10-30 01:29:13 +08:00
|
|
|
if (OpInfo.isIndirect) {
|
2011-07-18 12:54:35 +08:00
|
|
|
llvm::PointerType *PtrTy = dyn_cast<PointerType>(OpTy);
|
2010-10-30 01:29:13 +08:00
|
|
|
if (!PtrTy)
|
|
|
|
report_fatal_error("Indirect operand for inline asm not a pointer!");
|
|
|
|
OpTy = PtrTy->getElementType();
|
|
|
|
}
|
2011-06-18 04:41:29 +08:00
|
|
|
|
2011-05-10 04:04:43 +08:00
|
|
|
// Look for vector wrapped in a struct. e.g. { <16 x i8> }.
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *STy = dyn_cast<StructType>(OpTy))
|
2011-05-10 04:04:43 +08:00
|
|
|
if (STy->getNumElements() == 1)
|
|
|
|
OpTy = STy->getElementType(0);
|
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
// If OpTy is not a single value, it may be a struct/union that we
|
|
|
|
// can tile with integers.
|
|
|
|
if (!OpTy->isSingleValueType() && OpTy->isSized()) {
|
|
|
|
unsigned BitSize = TD->getTypeSizeInBits(OpTy);
|
|
|
|
switch (BitSize) {
|
|
|
|
default: break;
|
|
|
|
case 1:
|
|
|
|
case 8:
|
|
|
|
case 16:
|
|
|
|
case 32:
|
|
|
|
case 64:
|
|
|
|
case 128:
|
2010-11-09 09:15:07 +08:00
|
|
|
OpInfo.ConstraintVT =
|
2012-12-19 23:19:11 +08:00
|
|
|
MVT::getVT(IntegerType::get(OpTy->getContext(), BitSize), true);
|
2010-10-30 01:29:13 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-10-10 00:06:12 +08:00
|
|
|
} else if (PointerType *PT = dyn_cast<PointerType>(OpTy)) {
|
|
|
|
OpInfo.ConstraintVT = MVT::getIntegerVT(
|
|
|
|
8*TD->getPointerSize(PT->getAddressSpace()));
|
2010-10-30 01:29:13 +08:00
|
|
|
} else {
|
2012-12-19 23:19:11 +08:00
|
|
|
OpInfo.ConstraintVT = MVT::getVT(OpTy, true);
|
2010-10-30 01:29:13 +08:00
|
|
|
}
|
|
|
|
}
|
2010-09-14 02:15:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have multiple alternative constraints, select the best alternative.
|
|
|
|
if (ConstraintInfos.size()) {
|
|
|
|
if (maCount) {
|
|
|
|
unsigned bestMAIndex = 0;
|
|
|
|
int bestWeight = -1;
|
|
|
|
// weight: -1 = invalid match, and 0 = so-so match to 5 = good match.
|
|
|
|
int weight = -1;
|
|
|
|
unsigned maIndex;
|
|
|
|
// Compute the sums of the weights for each alternative, keeping track
|
|
|
|
// of the best (highest weight) one so far.
|
|
|
|
for (maIndex = 0; maIndex < maCount; ++maIndex) {
|
|
|
|
int weightSum = 0;
|
|
|
|
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
|
|
|
cIndex != eIndex; ++cIndex) {
|
|
|
|
AsmOperandInfo& OpInfo = ConstraintOperands[cIndex];
|
|
|
|
if (OpInfo.Type == InlineAsm::isClobber)
|
|
|
|
continue;
|
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
// If this is an output operand with a matching input operand,
|
|
|
|
// look up the matching input. If their types mismatch, e.g. one
|
|
|
|
// is an integer, the other is floating point, or their sizes are
|
|
|
|
// different, flag it as an maCantMatch.
|
2010-09-14 02:15:37 +08:00
|
|
|
if (OpInfo.hasMatchingInput()) {
|
|
|
|
AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
|
|
|
|
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
|
|
|
|
if ((OpInfo.ConstraintVT.isInteger() !=
|
|
|
|
Input.ConstraintVT.isInteger()) ||
|
|
|
|
(OpInfo.ConstraintVT.getSizeInBits() !=
|
|
|
|
Input.ConstraintVT.getSizeInBits())) {
|
|
|
|
weightSum = -1; // Can't match.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
weight = getMultipleConstraintMatchWeight(OpInfo, maIndex);
|
|
|
|
if (weight == -1) {
|
|
|
|
weightSum = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
weightSum += weight;
|
|
|
|
}
|
|
|
|
// Update best.
|
|
|
|
if (weightSum > bestWeight) {
|
|
|
|
bestWeight = weightSum;
|
|
|
|
bestMAIndex = maIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now select chosen alternative in each constraint.
|
|
|
|
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
|
|
|
cIndex != eIndex; ++cIndex) {
|
|
|
|
AsmOperandInfo& cInfo = ConstraintOperands[cIndex];
|
|
|
|
if (cInfo.Type == InlineAsm::isClobber)
|
|
|
|
continue;
|
|
|
|
cInfo.selectAlternative(bestMAIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check and hook up tied operands, choose constraint code to use.
|
|
|
|
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
|
|
|
cIndex != eIndex; ++cIndex) {
|
|
|
|
AsmOperandInfo& OpInfo = ConstraintOperands[cIndex];
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-09-14 02:15:37 +08:00
|
|
|
// If this is an output operand with a matching input operand, look up the
|
|
|
|
// matching input. If their types mismatch, e.g. one is an integer, the
|
|
|
|
// other is floating point, or their sizes are different, flag it as an
|
|
|
|
// error.
|
|
|
|
if (OpInfo.hasMatchingInput()) {
|
|
|
|
AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
|
2010-10-30 01:29:13 +08:00
|
|
|
|
2010-09-14 02:15:37 +08:00
|
|
|
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
|
2012-07-19 08:04:14 +08:00
|
|
|
std::pair<unsigned, const TargetRegisterClass*> MatchRC =
|
|
|
|
getRegForInlineAsmConstraint(OpInfo.ConstraintCode,
|
|
|
|
OpInfo.ConstraintVT);
|
|
|
|
std::pair<unsigned, const TargetRegisterClass*> InputRC =
|
|
|
|
getRegForInlineAsmConstraint(Input.ConstraintCode,
|
|
|
|
Input.ConstraintVT);
|
2010-09-14 02:15:37 +08:00
|
|
|
if ((OpInfo.ConstraintVT.isInteger() !=
|
|
|
|
Input.ConstraintVT.isInteger()) ||
|
2011-07-15 04:13:52 +08:00
|
|
|
(MatchRC.second != InputRC.second)) {
|
2010-09-14 02:15:37 +08:00
|
|
|
report_fatal_error("Unsupported asm: input constraint"
|
|
|
|
" with a matching output constraint of"
|
|
|
|
" incompatible type!");
|
|
|
|
}
|
|
|
|
}
|
2010-10-30 01:29:13 +08:00
|
|
|
|
2010-09-14 02:15:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ConstraintOperands;
|
|
|
|
}
|
|
|
|
|
2008-10-18 00:21:11 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
/// getConstraintGenerality - Return an integer indicating how general CT
|
|
|
|
/// is.
|
|
|
|
static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
|
|
|
|
switch (CT) {
|
|
|
|
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;
|
|
|
|
}
|
2012-01-11 02:08:01 +08:00
|
|
|
llvm_unreachable("Invalid constraint type");
|
2008-04-27 08:09:47 +08:00
|
|
|
}
|
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
/// Examine constraint type and operand type and determine a weight value.
|
2010-09-14 02:15:37 +08:00
|
|
|
/// This object must already have been set up with the operand type
|
|
|
|
/// and the current alternative constraint selected.
|
2010-10-30 01:29:13 +08:00
|
|
|
TargetLowering::ConstraintWeight
|
|
|
|
TargetLowering::getMultipleConstraintMatchWeight(
|
2010-09-14 02:15:37 +08:00
|
|
|
AsmOperandInfo &info, int maIndex) const {
|
2010-10-30 01:29:13 +08:00
|
|
|
InlineAsm::ConstraintCodeVector *rCodes;
|
2010-09-22 06:04:54 +08:00
|
|
|
if (maIndex >= (int)info.multipleAlternatives.size())
|
|
|
|
rCodes = &info.Codes;
|
|
|
|
else
|
|
|
|
rCodes = &info.multipleAlternatives[maIndex].Codes;
|
2010-10-30 01:29:13 +08:00
|
|
|
ConstraintWeight BestWeight = CW_Invalid;
|
2010-09-14 02:15:37 +08:00
|
|
|
|
|
|
|
// Loop over the options, keeping track of the most general one.
|
2010-09-22 06:04:54 +08:00
|
|
|
for (unsigned i = 0, e = rCodes->size(); i != e; ++i) {
|
2010-10-30 01:29:13 +08:00
|
|
|
ConstraintWeight weight =
|
|
|
|
getSingleConstraintMatchWeight(info, (*rCodes)[i].c_str());
|
2010-09-14 02:15:37 +08:00
|
|
|
if (weight > BestWeight)
|
|
|
|
BestWeight = weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BestWeight;
|
|
|
|
}
|
|
|
|
|
2010-10-30 01:29:13 +08:00
|
|
|
/// Examine constraint type and operand type and determine a weight value.
|
2010-09-14 02:15:37 +08:00
|
|
|
/// This object must already have been set up with the operand type
|
|
|
|
/// and the current alternative constraint selected.
|
2010-10-30 01:29:13 +08:00
|
|
|
TargetLowering::ConstraintWeight
|
|
|
|
TargetLowering::getSingleConstraintMatchWeight(
|
2010-09-14 02:15:37 +08:00
|
|
|
AsmOperandInfo &info, const char *constraint) const {
|
2010-10-30 01:29:13 +08:00
|
|
|
ConstraintWeight weight = CW_Invalid;
|
2010-09-14 02:15:37 +08:00
|
|
|
Value *CallOperandVal = info.CallOperandVal;
|
|
|
|
// If we don't have a value, we can't do a match,
|
|
|
|
// but allow it at the lowest weight.
|
|
|
|
if (CallOperandVal == NULL)
|
2010-10-30 01:29:13 +08:00
|
|
|
return CW_Default;
|
2010-09-14 02:15:37 +08:00
|
|
|
// Look at the constraint type.
|
|
|
|
switch (*constraint) {
|
|
|
|
case 'i': // immediate integer.
|
|
|
|
case 'n': // immediate integer with a known value.
|
2010-10-30 01:29:13 +08:00
|
|
|
if (isa<ConstantInt>(CallOperandVal))
|
|
|
|
weight = CW_Constant;
|
2010-09-14 02:15:37 +08:00
|
|
|
break;
|
|
|
|
case 's': // non-explicit intregal immediate.
|
2010-10-30 01:29:13 +08:00
|
|
|
if (isa<GlobalValue>(CallOperandVal))
|
|
|
|
weight = CW_Constant;
|
|
|
|
break;
|
|
|
|
case 'E': // immediate float if host format.
|
|
|
|
case 'F': // immediate float.
|
|
|
|
if (isa<ConstantFP>(CallOperandVal))
|
|
|
|
weight = CW_Constant;
|
2010-09-14 02:15:37 +08:00
|
|
|
break;
|
2010-10-30 01:29:13 +08:00
|
|
|
case '<': // memory operand with autodecrement.
|
|
|
|
case '>': // memory operand with autoincrement.
|
2010-09-14 02:15:37 +08:00
|
|
|
case 'm': // memory operand.
|
|
|
|
case 'o': // offsettable memory operand
|
|
|
|
case 'V': // non-offsettable memory operand
|
2010-10-30 01:29:13 +08:00
|
|
|
weight = CW_Memory;
|
2010-09-14 02:15:37 +08:00
|
|
|
break;
|
2010-10-30 01:29:13 +08:00
|
|
|
case 'r': // general register.
|
2010-09-14 02:15:37 +08:00
|
|
|
case 'g': // general register, memory operand or immediate integer.
|
2010-10-30 01:29:13 +08:00
|
|
|
// note: Clang converts "g" to "imr".
|
|
|
|
if (CallOperandVal->getType()->isIntegerTy())
|
|
|
|
weight = CW_Register;
|
2010-09-14 02:15:37 +08:00
|
|
|
break;
|
2010-10-30 01:29:13 +08:00
|
|
|
case 'X': // any operand.
|
2010-09-14 02:15:37 +08:00
|
|
|
default:
|
2010-10-30 01:29:13 +08:00
|
|
|
weight = CW_Default;
|
2010-09-14 02:15:37 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return weight;
|
|
|
|
}
|
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
/// 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 09:49:46 +08:00
|
|
|
/// This is somewhat tricky: constraints fall into four classes:
|
2008-04-27 08:09:47 +08: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,
|
2010-06-26 05:55:36 +08:00
|
|
|
const TargetLowering &TLI,
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Op, SelectionDAG *DAG) {
|
2008-04-27 08:09:47 +08:00
|
|
|
assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
|
|
|
|
unsigned BestIdx = 0;
|
|
|
|
TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown;
|
|
|
|
int BestGenerality = -1;
|
2010-06-29 06:09:45 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
// 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]);
|
2010-06-29 06:09:45 +08:00
|
|
|
|
2008-04-27 08:37:18 +08: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-29 05:40:38 +08:00
|
|
|
if (CType == TargetLowering::C_Other && Op.getNode()) {
|
2008-04-27 08:37:18 +08:00
|
|
|
assert(OpInfo.Codes[i].size() == 1 &&
|
|
|
|
"Unhandled multi-letter 'other' constraint");
|
2008-07-28 05:46:04 +08:00
|
|
|
std::vector<SDValue> ResultOps;
|
2011-06-03 07:16:42 +08:00
|
|
|
TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i],
|
2008-04-27 08:37:18 +08:00
|
|
|
ResultOps, *DAG);
|
|
|
|
if (!ResultOps.empty()) {
|
|
|
|
BestType = CType;
|
|
|
|
BestIdx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2010-06-29 06:09:45 +08:00
|
|
|
// Things with matching constraints can only be registers, per gcc
|
|
|
|
// documentation. This mainly affects "g" constraints.
|
|
|
|
if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput())
|
|
|
|
continue;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-04-27 08:09:47 +08: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;
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
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 08:37:18 +08:00
|
|
|
void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo,
|
2010-11-23 11:31:01 +08:00
|
|
|
SDValue Op,
|
2008-04-27 08:37:18 +08:00
|
|
|
SelectionDAG *DAG) const {
|
2008-04-27 08:09:47 +08:00
|
|
|
assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
// Single-letter constraints ('r') are very common.
|
|
|
|
if (OpInfo.Codes.size() == 1) {
|
|
|
|
OpInfo.ConstraintCode = OpInfo.Codes[0];
|
|
|
|
OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
|
|
|
|
} else {
|
2010-06-26 05:55:36 +08:00
|
|
|
ChooseConstraint(OpInfo, *this, Op, DAG);
|
2008-04-27 08:09:47 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
// 'X' matches anything.
|
|
|
|
if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
|
|
|
|
// Labels and constants are handled elsewhere ('X' is the only thing
|
2009-07-08 07:26:33 +08:00
|
|
|
// that matches labels). For Functions, the type here is the type of
|
2009-07-21 07:27:39 +08:00
|
|
|
// the result, which is not what we want to look at; leave them alone.
|
|
|
|
Value *v = OpInfo.CallOperandVal;
|
2009-07-08 07:26:33 +08:00
|
|
|
if (isa<BasicBlock>(v) || isa<ConstantInt>(v) || isa<Function>(v)) {
|
|
|
|
OpInfo.CallOperandVal = v;
|
2008-04-27 08:09:47 +08:00
|
|
|
return;
|
2009-07-08 07:26:33 +08:00
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-04-27 08:09:47 +08:00
|
|
|
// 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-14 07:18:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loop Strength Reduction hooks
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-03-31 07:14:50 +08:00
|
|
|
/// isLegalAddressingMode - Return true if the addressing mode represented
|
|
|
|
/// by AM is legal for this target, for a load/store of the specified type.
|
2010-11-23 11:31:01 +08:00
|
|
|
bool TargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *Ty) const {
|
2007-03-31 07:14:50 +08:00
|
|
|
// 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;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-03-31 07:14:50 +08:00
|
|
|
// No global is ever allowed as a base.
|
|
|
|
if (AM.BaseGV)
|
|
|
|
return false;
|
2010-11-23 11:31:01 +08:00
|
|
|
|
|
|
|
// Only support r+r,
|
2007-03-31 07:14:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2007-03-31 07:14:50 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Emit a more efficient magic number multiplication for exact sdivs.
We have to do this in DAGBuilder instead of DAGCombiner, because the exact bit is lost after building.
struct foo { char x[24]; };
long bar(struct foo *a, struct foo *b) { return a-b; }
is now compiled into
movl 4(%esp), %eax
subl 8(%esp), %eax
sarl $3, %eax
imull $-1431655765, %eax, %eax
instead of
movl 4(%esp), %eax
subl 8(%esp), %eax
movl $715827883, %ecx
imull %ecx
movl %edx, %eax
shrl $31, %eax
sarl $2, %edx
addl %eax, %edx
movl %edx, %eax
llvm-svn: 134695
2011-07-08 18:31:30 +08:00
|
|
|
/// BuildExactDiv - Given an exact SDIV by a constant, create a multiplication
|
|
|
|
/// with the multiplicative inverse of the constant.
|
|
|
|
SDValue TargetLowering::BuildExactSDIV(SDValue Op1, SDValue Op2, DebugLoc dl,
|
|
|
|
SelectionDAG &DAG) const {
|
|
|
|
ConstantSDNode *C = cast<ConstantSDNode>(Op2);
|
|
|
|
APInt d = C->getAPIntValue();
|
|
|
|
assert(d != 0 && "Division by zero!");
|
|
|
|
|
|
|
|
// Shift the value upfront if it is even, so the LSB is one.
|
|
|
|
unsigned ShAmt = d.countTrailingZeros();
|
|
|
|
if (ShAmt) {
|
|
|
|
// TODO: For UDIV use SRL instead of SRA.
|
|
|
|
SDValue Amt = DAG.getConstant(ShAmt, getShiftAmountTy(Op1.getValueType()));
|
|
|
|
Op1 = DAG.getNode(ISD::SRA, dl, Op1.getValueType(), Op1, Amt);
|
|
|
|
d = d.ashr(ShAmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the multiplicative inverse, using Newton's method.
|
|
|
|
APInt t, xn = d;
|
|
|
|
while ((t = d*xn) != 1)
|
|
|
|
xn *= APInt(d.getBitWidth(), 2) - t;
|
|
|
|
|
|
|
|
Op2 = DAG.getConstant(xn, Op1.getValueType());
|
|
|
|
return DAG.getNode(ISD::MUL, dl, Op1.getValueType(), Op1, Op2);
|
|
|
|
}
|
|
|
|
|
2006-05-17 01:42:15 +08:00
|
|
|
/// 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>
|
2011-11-08 01:09:05 +08:00
|
|
|
SDValue TargetLowering::
|
|
|
|
BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization,
|
2012-12-11 06:00:20 +08:00
|
|
|
std::vector<SDNode*> *Created) const {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = N->getValueType(0);
|
2009-02-03 08:47:48 +08:00
|
|
|
DebugLoc dl= N->getDebugLoc();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-05-17 01:42:15 +08:00
|
|
|
// Check to see if we can do this.
|
2008-11-30 14:35:39 +08:00
|
|
|
// FIXME: We should be more aggressive here.
|
|
|
|
if (!isTypeLegal(VT))
|
|
|
|
return SDValue();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2008-11-30 14:35:39 +08:00
|
|
|
APInt d = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
|
2009-04-30 18:15:35 +08:00
|
|
|
APInt::ms magics = d.magic();
|
2010-11-23 11:31:01 +08:00
|
|
|
|
2006-05-17 01:42:15 +08:00
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
2008-11-30 14:35:39 +08:00
|
|
|
// FIXME: We should support doing a MUL in a wider type
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Q;
|
2011-11-08 01:09:05 +08:00
|
|
|
if (IsAfterLegalization ? isOperationLegal(ISD::MULHS, VT) :
|
|
|
|
isOperationLegalOrCustom(ISD::MULHS, VT))
|
2009-02-03 08:47:48 +08:00
|
|
|
Q = DAG.getNode(ISD::MULHS, dl, VT, N->getOperand(0),
|
2007-10-09 02:33:35 +08:00
|
|
|
DAG.getConstant(magics.m, VT));
|
2011-11-08 01:09:05 +08:00
|
|
|
else if (IsAfterLegalization ? isOperationLegal(ISD::SMUL_LOHI, VT) :
|
|
|
|
isOperationLegalOrCustom(ISD::SMUL_LOHI, VT))
|
2009-02-03 08:47:48 +08:00
|
|
|
Q = SDValue(DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(VT, VT),
|
2007-10-09 02:33:35 +08:00
|
|
|
N->getOperand(0),
|
2008-08-29 05:40:38 +08:00
|
|
|
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
2007-10-09 02:33:35 +08:00
|
|
|
else
|
2008-07-28 05:46:04 +08:00
|
|
|
return SDValue(); // No mulhs or equvialent
|
2006-05-17 01:42:15 +08:00
|
|
|
// If d > 0 and m < 0, add the numerator
|
2010-11-23 11:31:01 +08:00
|
|
|
if (d.isStrictlyPositive() && magics.m.isNegative()) {
|
2009-02-03 08:47:48 +08:00
|
|
|
Q = DAG.getNode(ISD::ADD, dl, VT, Q, N->getOperand(0));
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-17 01:42:15 +08:00
|
|
|
}
|
|
|
|
// If d < 0 and m > 0, subtract the numerator.
|
2008-11-30 14:35:39 +08:00
|
|
|
if (d.isNegative() && magics.m.isStrictlyPositive()) {
|
2009-02-03 08:47:48 +08:00
|
|
|
Q = DAG.getNode(ISD::SUB, dl, VT, Q, N->getOperand(0));
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-17 01:42:15 +08:00
|
|
|
}
|
|
|
|
// Shift right algebraic if shift value is nonzero
|
|
|
|
if (magics.s > 0) {
|
2010-11-23 11:31:01 +08:00
|
|
|
Q = DAG.getNode(ISD::SRA, dl, VT, Q,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-17 01:42:15 +08:00
|
|
|
}
|
|
|
|
// Extract the sign bit and add it to the quotient
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue T =
|
2009-02-03 08:47:48 +08:00
|
|
|
DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1,
|
2011-02-26 05:41:48 +08:00
|
|
|
getShiftAmountTy(Q.getValueType())));
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(T.getNode());
|
2009-02-03 08:47:48 +08:00
|
|
|
return DAG.getNode(ISD::ADD, dl, VT, Q, T);
|
2006-05-17 01:42:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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>
|
2011-11-08 01:09:05 +08:00
|
|
|
SDValue TargetLowering::
|
|
|
|
BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization,
|
2012-12-11 06:00:20 +08:00
|
|
|
std::vector<SDNode*> *Created) const {
|
2009-08-11 06:56:29 +08:00
|
|
|
EVT VT = N->getValueType(0);
|
2009-02-03 08:47:48 +08:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-11-30 14:02:26 +08:00
|
|
|
|
2006-05-17 01:42:15 +08:00
|
|
|
// Check to see if we can do this.
|
2008-11-30 14:02:26 +08: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.
|
BuildUDIV: If the divisor is even we can simplify the fixup of the multiplied value by introducing an early shift.
This allows us to compile "unsigned foo(unsigned x) { return x/28; }" into
shrl $2, %edi
imulq $613566757, %rdi, %rax
shrq $32, %rax
ret
instead of
movl %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $4, %eax
on x86_64
llvm-svn: 127829
2011-03-18 04:39:14 +08:00
|
|
|
const APInt &N1C = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
|
|
|
|
APInt::mu magics = N1C.magicu();
|
|
|
|
|
|
|
|
SDValue Q = N->getOperand(0);
|
|
|
|
|
|
|
|
// If the divisor is even, we can avoid using the expensive fixup by shifting
|
|
|
|
// the divided value upfront.
|
|
|
|
if (magics.a != 0 && !N1C[0]) {
|
|
|
|
unsigned Shift = N1C.countTrailingZeros();
|
|
|
|
Q = DAG.getNode(ISD::SRL, dl, VT, Q,
|
|
|
|
DAG.getConstant(Shift, getShiftAmountTy(Q.getValueType())));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(Q.getNode());
|
|
|
|
|
|
|
|
// Get magic number for the shifted divisor.
|
|
|
|
magics = N1C.lshr(Shift).magicu(Shift);
|
|
|
|
assert(magics.a == 0 && "Should use cheap fixup now");
|
|
|
|
}
|
2008-11-30 14:02:26 +08:00
|
|
|
|
2006-05-17 01:42:15 +08:00
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
2008-11-30 14:02:26 +08:00
|
|
|
// FIXME: We should support doing a MUL in a wider type
|
2011-11-08 01:09:05 +08:00
|
|
|
if (IsAfterLegalization ? isOperationLegal(ISD::MULHU, VT) :
|
|
|
|
isOperationLegalOrCustom(ISD::MULHU, VT))
|
BuildUDIV: If the divisor is even we can simplify the fixup of the multiplied value by introducing an early shift.
This allows us to compile "unsigned foo(unsigned x) { return x/28; }" into
shrl $2, %edi
imulq $613566757, %rdi, %rax
shrq $32, %rax
ret
instead of
movl %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $4, %eax
on x86_64
llvm-svn: 127829
2011-03-18 04:39:14 +08:00
|
|
|
Q = DAG.getNode(ISD::MULHU, dl, VT, Q, DAG.getConstant(magics.m, VT));
|
2011-11-08 01:09:05 +08:00
|
|
|
else if (IsAfterLegalization ? isOperationLegal(ISD::UMUL_LOHI, VT) :
|
|
|
|
isOperationLegalOrCustom(ISD::UMUL_LOHI, VT))
|
BuildUDIV: If the divisor is even we can simplify the fixup of the multiplied value by introducing an early shift.
This allows us to compile "unsigned foo(unsigned x) { return x/28; }" into
shrl $2, %edi
imulq $613566757, %rdi, %rax
shrq $32, %rax
ret
instead of
movl %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $4, %eax
on x86_64
llvm-svn: 127829
2011-03-18 04:39:14 +08:00
|
|
|
Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), Q,
|
|
|
|
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
2007-10-09 02:33:35 +08:00
|
|
|
else
|
2008-07-28 05:46:04 +08:00
|
|
|
return SDValue(); // No mulhu or equvialent
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(Q.getNode());
|
2006-05-17 01:42:15 +08:00
|
|
|
|
|
|
|
if (magics.a == 0) {
|
BuildUDIV: If the divisor is even we can simplify the fixup of the multiplied value by introducing an early shift.
This allows us to compile "unsigned foo(unsigned x) { return x/28; }" into
shrl $2, %edi
imulq $613566757, %rdi, %rax
shrq $32, %rax
ret
instead of
movl %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $4, %eax
on x86_64
llvm-svn: 127829
2011-03-18 04:39:14 +08:00
|
|
|
assert(magics.s < N1C.getBitWidth() &&
|
2008-11-30 14:02:26 +08:00
|
|
|
"We shouldn't generate an undefined shift!");
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getNode(ISD::SRL, dl, VT, Q,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
|
2006-05-17 01:42:15 +08:00
|
|
|
} else {
|
2009-02-03 08:47:48 +08:00
|
|
|
SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q);
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(NPQ.getNode());
|
2010-11-23 11:31:01 +08:00
|
|
|
NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(1, getShiftAmountTy(NPQ.getValueType())));
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(NPQ.getNode());
|
2009-02-03 08:47:48 +08:00
|
|
|
NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q);
|
2006-05-17 01:42:15 +08:00
|
|
|
if (Created)
|
2008-08-29 05:40:38 +08:00
|
|
|
Created->push_back(NPQ.getNode());
|
2010-11-23 11:31:01 +08:00
|
|
|
return DAG.getNode(ISD::SRL, dl, VT, NPQ,
|
2011-02-26 05:41:48 +08:00
|
|
|
DAG.getConstant(magics.s-1, getShiftAmountTy(NPQ.getValueType())));
|
2006-05-17 01:42:15 +08:00
|
|
|
}
|
|
|
|
}
|