2005-01-07 07:44:53 +00:00
|
|
|
//===-- TargetLowering.cpp - Implement the TargetLowering class -----------===//
|
2005-04-21 22:55:34 +00:00
|
|
|
//
|
2005-01-07 07:44:53 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
2005-04-21 22:55:34 +00:00
|
|
|
//
|
2005-01-07 07:44:53 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This implements the TargetLowering class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Target/TargetLowering.h"
|
2006-05-12 06:33:49 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2006-01-26 20:37:03 +00:00
|
|
|
#include "llvm/Target/MRegisterInfo.h"
|
2006-03-31 00:28:56 +00:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2006-01-26 20:37:03 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2006-01-30 04:09:27 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2005-01-07 07:44:53 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2007-01-12 02:11:51 +00:00
|
|
|
/// InitLibcallNames - Set default libcall names.
|
|
|
|
///
|
2007-01-12 22:51:10 +00:00
|
|
|
static void InitLibcallNames(const char **Names) {
|
2007-01-12 02:11:51 +00:00
|
|
|
Names[RTLIB::SHL_I32] = "__ashlsi3";
|
|
|
|
Names[RTLIB::SHL_I64] = "__ashldi3";
|
|
|
|
Names[RTLIB::SRL_I32] = "__lshrsi3";
|
|
|
|
Names[RTLIB::SRL_I64] = "__lshrdi3";
|
|
|
|
Names[RTLIB::SRA_I32] = "__ashrsi3";
|
|
|
|
Names[RTLIB::SRA_I64] = "__ashrdi3";
|
|
|
|
Names[RTLIB::MUL_I32] = "__mulsi3";
|
|
|
|
Names[RTLIB::MUL_I64] = "__muldi3";
|
|
|
|
Names[RTLIB::SDIV_I32] = "__divsi3";
|
|
|
|
Names[RTLIB::SDIV_I64] = "__divdi3";
|
|
|
|
Names[RTLIB::UDIV_I32] = "__udivsi3";
|
|
|
|
Names[RTLIB::UDIV_I64] = "__udivdi3";
|
|
|
|
Names[RTLIB::SREM_I32] = "__modsi3";
|
|
|
|
Names[RTLIB::SREM_I64] = "__moddi3";
|
|
|
|
Names[RTLIB::UREM_I32] = "__umodsi3";
|
|
|
|
Names[RTLIB::UREM_I64] = "__umoddi3";
|
|
|
|
Names[RTLIB::NEG_I32] = "__negsi2";
|
|
|
|
Names[RTLIB::NEG_I64] = "__negdi2";
|
|
|
|
Names[RTLIB::ADD_F32] = "__addsf3";
|
|
|
|
Names[RTLIB::ADD_F64] = "__adddf3";
|
|
|
|
Names[RTLIB::SUB_F32] = "__subsf3";
|
|
|
|
Names[RTLIB::SUB_F64] = "__subdf3";
|
|
|
|
Names[RTLIB::MUL_F32] = "__mulsf3";
|
|
|
|
Names[RTLIB::MUL_F64] = "__muldf3";
|
|
|
|
Names[RTLIB::DIV_F32] = "__divsf3";
|
|
|
|
Names[RTLIB::DIV_F64] = "__divdf3";
|
|
|
|
Names[RTLIB::REM_F32] = "fmodf";
|
|
|
|
Names[RTLIB::REM_F64] = "fmod";
|
|
|
|
Names[RTLIB::NEG_F32] = "__negsf2";
|
|
|
|
Names[RTLIB::NEG_F64] = "__negdf2";
|
|
|
|
Names[RTLIB::POWI_F32] = "__powisf2";
|
|
|
|
Names[RTLIB::POWI_F64] = "__powidf2";
|
|
|
|
Names[RTLIB::SQRT_F32] = "sqrtf";
|
|
|
|
Names[RTLIB::SQRT_F64] = "sqrt";
|
|
|
|
Names[RTLIB::SIN_F32] = "sinf";
|
|
|
|
Names[RTLIB::SIN_F64] = "sin";
|
|
|
|
Names[RTLIB::COS_F32] = "cosf";
|
|
|
|
Names[RTLIB::COS_F64] = "cos";
|
|
|
|
Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2";
|
|
|
|
Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2";
|
|
|
|
Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi";
|
|
|
|
Names[RTLIB::FPTOSINT_F64_I32] = "__fixdfsi";
|
|
|
|
Names[RTLIB::FPTOSINT_F64_I64] = "__fixdfdi";
|
|
|
|
Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi";
|
|
|
|
Names[RTLIB::FPTOUINT_F64_I32] = "__fixunsdfsi";
|
|
|
|
Names[RTLIB::FPTOUINT_F64_I64] = "__fixunsdfdi";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf";
|
|
|
|
Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf";
|
|
|
|
Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf";
|
|
|
|
Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf";
|
|
|
|
Names[RTLIB::OEQ_F32] = "__eqsf2";
|
|
|
|
Names[RTLIB::OEQ_F64] = "__eqdf2";
|
|
|
|
Names[RTLIB::UNE_F32] = "__nesf2";
|
|
|
|
Names[RTLIB::UNE_F64] = "__nedf2";
|
|
|
|
Names[RTLIB::OGE_F32] = "__gesf2";
|
|
|
|
Names[RTLIB::OGE_F64] = "__gedf2";
|
|
|
|
Names[RTLIB::OLT_F32] = "__ltsf2";
|
|
|
|
Names[RTLIB::OLT_F64] = "__ltdf2";
|
|
|
|
Names[RTLIB::OLE_F32] = "__lesf2";
|
|
|
|
Names[RTLIB::OLE_F64] = "__ledf2";
|
|
|
|
Names[RTLIB::OGT_F32] = "__gtsf2";
|
|
|
|
Names[RTLIB::OGT_F64] = "__gtdf2";
|
|
|
|
Names[RTLIB::UO_F32] = "__unordsf2";
|
|
|
|
Names[RTLIB::UO_F64] = "__unorddf2";
|
2007-01-31 09:29:11 +00:00
|
|
|
Names[RTLIB::O_F32] = "__unordsf2";
|
|
|
|
Names[RTLIB::O_F64] = "__unorddf2";
|
|
|
|
}
|
|
|
|
|
|
|
|
/// InitCmpLibcallCCs - Set default comparison libcall CC.
|
|
|
|
///
|
|
|
|
static void InitCmpLibcallCCs(ISD::CondCode *CCs) {
|
|
|
|
memset(CCs, ISD::SETCC_INVALID, sizeof(ISD::CondCode)*RTLIB::UNKNOWN_LIBCALL);
|
|
|
|
CCs[RTLIB::OEQ_F32] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::OEQ_F64] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::UNE_F32] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::UNE_F64] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::OGE_F32] = ISD::SETGE;
|
|
|
|
CCs[RTLIB::OGE_F64] = ISD::SETGE;
|
|
|
|
CCs[RTLIB::OLT_F32] = ISD::SETLT;
|
|
|
|
CCs[RTLIB::OLT_F64] = ISD::SETLT;
|
|
|
|
CCs[RTLIB::OLE_F32] = ISD::SETLE;
|
|
|
|
CCs[RTLIB::OLE_F64] = ISD::SETLE;
|
|
|
|
CCs[RTLIB::OGT_F32] = ISD::SETGT;
|
|
|
|
CCs[RTLIB::OGT_F64] = ISD::SETGT;
|
|
|
|
CCs[RTLIB::UO_F32] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::UO_F64] = ISD::SETNE;
|
|
|
|
CCs[RTLIB::O_F32] = ISD::SETEQ;
|
|
|
|
CCs[RTLIB::O_F64] = ISD::SETEQ;
|
2007-01-12 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
TargetLowering::TargetLowering(TargetMachine &tm)
|
2006-01-29 08:41:12 +00:00
|
|
|
: TM(tm), TD(TM.getTargetData()) {
|
2006-03-03 06:58:59 +00:00
|
|
|
assert(ISD::BUILTIN_OP_END <= 156 &&
|
2005-01-07 07:44:53 +00:00
|
|
|
"Fixed size array in TargetLowering is not large enough!");
|
2005-01-16 07:28:11 +00:00
|
|
|
// All operations default to being supported.
|
|
|
|
memset(OpActions, 0, sizeof(OpActions));
|
2006-10-04 00:56:09 +00:00
|
|
|
memset(LoadXActions, 0, sizeof(LoadXActions));
|
2006-10-13 21:14:26 +00:00
|
|
|
memset(&StoreXActions, 0, sizeof(StoreXActions));
|
2006-11-09 18:56:43 +00:00
|
|
|
// Initialize all indexed load / store to expand.
|
|
|
|
for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) {
|
|
|
|
for (unsigned IM = (unsigned)ISD::PRE_INC;
|
|
|
|
IM != (unsigned)ISD::LAST_INDEXED_MODE; ++IM) {
|
|
|
|
setIndexedLoadAction(IM, (MVT::ValueType)VT, Expand);
|
|
|
|
setIndexedStoreAction(IM, (MVT::ValueType)VT, Expand);
|
|
|
|
}
|
|
|
|
}
|
2005-01-07 07:44:53 +00:00
|
|
|
|
2006-05-03 01:29:57 +00:00
|
|
|
IsLittleEndian = TD->isLittleEndian();
|
2006-10-06 22:52:08 +00:00
|
|
|
UsesGlobalOffsetTable = false;
|
2006-05-03 01:29:57 +00:00
|
|
|
ShiftAmountTy = SetCCResultTy = PointerTy = getValueType(TD->getIntPtrType());
|
2005-01-19 03:36:14 +00:00
|
|
|
ShiftAmtHandling = Undefined;
|
2005-01-07 07:44:53 +00:00
|
|
|
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
|
2006-03-01 04:52:55 +00:00
|
|
|
memset(TargetDAGCombineArray, 0,
|
|
|
|
sizeof(TargetDAGCombineArray)/sizeof(TargetDAGCombineArray[0]));
|
2006-02-14 08:38:30 +00:00
|
|
|
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
|
2005-08-27 19:09:02 +00:00
|
|
|
allowUnalignedMemoryAccesses = false;
|
2006-12-10 23:12:42 +00:00
|
|
|
UseUnderscoreSetJmp = false;
|
|
|
|
UseUnderscoreLongJmp = false;
|
2007-02-25 01:28:05 +00:00
|
|
|
SelectIsExpensive = false;
|
2005-10-21 00:02:42 +00:00
|
|
|
IntDivIsCheap = false;
|
|
|
|
Pow2DivIsCheap = false;
|
2006-01-25 18:57:15 +00:00
|
|
|
StackPointerRegisterToSaveRestore = 0;
|
2007-02-22 18:04:49 +00:00
|
|
|
ExceptionPointerRegister = 0;
|
|
|
|
ExceptionSelectorRegister = 0;
|
2006-01-25 18:52:42 +00:00
|
|
|
SchedPreferenceInfo = SchedulingForLatency;
|
2006-09-05 17:39:15 +00:00
|
|
|
JumpBufSize = 0;
|
2006-09-04 07:44:11 +00:00
|
|
|
JumpBufAlignment = 0;
|
2007-01-12 02:11:51 +00:00
|
|
|
|
|
|
|
InitLibcallNames(LibcallRoutineNames);
|
2007-01-31 09:29:11 +00:00
|
|
|
InitCmpLibcallCCs(CmpLibcallCCs);
|
2005-01-07 07:44:53 +00:00
|
|
|
}
|
|
|
|
|
2005-01-16 07:28:11 +00:00
|
|
|
TargetLowering::~TargetLowering() {}
|
|
|
|
|
2005-01-16 01:10:58 +00:00
|
|
|
/// setValueTypeAction - Set the action for a particular value type. This
|
|
|
|
/// assumes an action has not already been set for this value type.
|
2005-01-16 07:28:11 +00:00
|
|
|
static void SetValueTypeAction(MVT::ValueType VT,
|
|
|
|
TargetLowering::LegalizeAction Action,
|
2005-01-16 01:10:58 +00:00
|
|
|
TargetLowering &TLI,
|
|
|
|
MVT::ValueType *TransformToType,
|
2006-01-29 08:41:12 +00:00
|
|
|
TargetLowering::ValueTypeActionImpl &ValueTypeActions) {
|
|
|
|
ValueTypeActions.setTypeAction(VT, Action);
|
2005-01-16 07:28:11 +00:00
|
|
|
if (Action == TargetLowering::Promote) {
|
2005-01-16 01:10:58 +00:00
|
|
|
MVT::ValueType PromoteTo;
|
|
|
|
if (VT == MVT::f32)
|
|
|
|
PromoteTo = MVT::f64;
|
|
|
|
else {
|
|
|
|
unsigned LargerReg = VT+1;
|
2005-08-24 16:34:12 +00:00
|
|
|
while (!TLI.isTypeLegal((MVT::ValueType)LargerReg)) {
|
2005-01-16 01:10:58 +00:00
|
|
|
++LargerReg;
|
|
|
|
assert(MVT::isInteger((MVT::ValueType)LargerReg) &&
|
|
|
|
"Nothing to promote to??");
|
|
|
|
}
|
|
|
|
PromoteTo = (MVT::ValueType)LargerReg;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(MVT::isInteger(VT) == MVT::isInteger(PromoteTo) &&
|
|
|
|
MVT::isFloatingPoint(VT) == MVT::isFloatingPoint(PromoteTo) &&
|
|
|
|
"Can only promote from int->int or fp->fp!");
|
|
|
|
assert(VT < PromoteTo && "Must promote to a larger type!");
|
|
|
|
TransformToType[VT] = PromoteTo;
|
2005-01-16 07:28:11 +00:00
|
|
|
} else if (Action == TargetLowering::Expand) {
|
2006-12-09 02:42:38 +00:00
|
|
|
// f32 and f64 is each expanded to corresponding integer type of same size.
|
|
|
|
if (VT == MVT::f32)
|
|
|
|
TransformToType[VT] = MVT::i32;
|
|
|
|
else if (VT == MVT::f64)
|
|
|
|
TransformToType[VT] = MVT::i64;
|
|
|
|
else {
|
|
|
|
assert((VT == MVT::Vector || MVT::isInteger(VT)) && VT > MVT::i8 &&
|
|
|
|
"Cannot expand this type: target must support SOME integer reg!");
|
|
|
|
// Expand to the next smaller integer type!
|
|
|
|
TransformToType[VT] = (MVT::ValueType)(VT-1);
|
|
|
|
}
|
2005-01-16 01:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
/// computeRegisterProperties - Once all of the register classes are added,
|
|
|
|
/// this allows us to compute derived properties we expose.
|
|
|
|
void TargetLowering::computeRegisterProperties() {
|
2005-11-29 05:45:29 +00:00
|
|
|
assert(MVT::LAST_VALUETYPE <= 32 &&
|
2005-01-16 01:10:58 +00:00
|
|
|
"Too many value types for ValueTypeActions to hold!");
|
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
// Everything defaults to one.
|
|
|
|
for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i)
|
|
|
|
NumElementsForVT[i] = 1;
|
2005-04-21 22:55:34 +00:00
|
|
|
|
2005-01-07 07:44:53 +00:00
|
|
|
// Find the largest integer register class.
|
|
|
|
unsigned LargestIntReg = MVT::i128;
|
|
|
|
for (; RegClassForVT[LargestIntReg] == 0; --LargestIntReg)
|
|
|
|
assert(LargestIntReg != MVT::i1 && "No integer registers defined!");
|
|
|
|
|
|
|
|
// Every integer value type larger than this largest register takes twice as
|
|
|
|
// many registers to represent as the previous ValueType.
|
|
|
|
unsigned ExpandedReg = LargestIntReg; ++LargestIntReg;
|
|
|
|
for (++ExpandedReg; MVT::isInteger((MVT::ValueType)ExpandedReg);++ExpandedReg)
|
|
|
|
NumElementsForVT[ExpandedReg] = 2*NumElementsForVT[ExpandedReg-1];
|
|
|
|
|
2005-01-16 01:10:58 +00:00
|
|
|
// Inspect all of the ValueType's possible, deciding how to process them.
|
|
|
|
for (unsigned IntReg = MVT::i1; IntReg <= MVT::i128; ++IntReg)
|
|
|
|
// If we are expanding this type, expand it!
|
|
|
|
if (getNumElements((MVT::ValueType)IntReg) != 1)
|
2005-01-16 07:28:11 +00:00
|
|
|
SetValueTypeAction((MVT::ValueType)IntReg, Expand, *this, TransformToType,
|
2005-01-16 01:10:58 +00:00
|
|
|
ValueTypeActions);
|
2005-08-24 16:34:12 +00:00
|
|
|
else if (!isTypeLegal((MVT::ValueType)IntReg))
|
2005-01-16 01:10:58 +00:00
|
|
|
// Otherwise, if we don't have native support, we must promote to a
|
|
|
|
// larger type.
|
2005-01-16 07:28:11 +00:00
|
|
|
SetValueTypeAction((MVT::ValueType)IntReg, Promote, *this,
|
|
|
|
TransformToType, ValueTypeActions);
|
2005-01-16 01:20:18 +00:00
|
|
|
else
|
|
|
|
TransformToType[(MVT::ValueType)IntReg] = (MVT::ValueType)IntReg;
|
2005-04-21 22:55:34 +00:00
|
|
|
|
2006-12-09 02:42:38 +00:00
|
|
|
// If the target does not have native F64 support, expand it to I64. We will
|
|
|
|
// be generating soft float library calls. If the target does not have native
|
|
|
|
// support for F32, promote it to F64 if it is legal. Otherwise, expand it to
|
|
|
|
// I32.
|
|
|
|
if (isTypeLegal(MVT::f64))
|
|
|
|
TransformToType[MVT::f64] = MVT::f64;
|
|
|
|
else {
|
|
|
|
NumElementsForVT[MVT::f64] = NumElementsForVT[MVT::i64];
|
|
|
|
SetValueTypeAction(MVT::f64, Expand, *this, TransformToType,
|
|
|
|
ValueTypeActions);
|
|
|
|
}
|
|
|
|
if (isTypeLegal(MVT::f32))
|
2005-01-16 01:20:18 +00:00
|
|
|
TransformToType[MVT::f32] = MVT::f32;
|
2006-12-09 02:42:38 +00:00
|
|
|
else if (isTypeLegal(MVT::f64))
|
|
|
|
SetValueTypeAction(MVT::f32, Promote, *this, TransformToType,
|
|
|
|
ValueTypeActions);
|
|
|
|
else {
|
|
|
|
NumElementsForVT[MVT::f32] = NumElementsForVT[MVT::i32];
|
|
|
|
SetValueTypeAction(MVT::f32, Expand, *this, TransformToType,
|
|
|
|
ValueTypeActions);
|
|
|
|
}
|
2005-11-22 01:29:36 +00:00
|
|
|
|
|
|
|
// Set MVT::Vector to always be Expanded
|
|
|
|
SetValueTypeAction(MVT::Vector, Expand, *this, TransformToType,
|
|
|
|
ValueTypeActions);
|
2006-03-16 19:50:01 +00:00
|
|
|
|
|
|
|
// Loop over all of the legal vector value types, specifying an identity type
|
|
|
|
// transformation.
|
|
|
|
for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE;
|
2006-03-23 23:24:51 +00:00
|
|
|
i <= MVT::LAST_VECTOR_VALUETYPE; ++i) {
|
2006-03-16 19:50:01 +00:00
|
|
|
if (isTypeLegal((MVT::ValueType)i))
|
|
|
|
TransformToType[i] = (MVT::ValueType)i;
|
|
|
|
}
|
2005-01-16 01:10:58 +00:00
|
|
|
}
|
2005-01-16 07:28:11 +00:00
|
|
|
|
2005-12-20 06:22:03 +00:00
|
|
|
const char *TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-12-21 23:05:39 +00:00
|
|
|
|
2007-02-15 02:26:10 +00:00
|
|
|
/// getVectorTypeBreakdown - Packed types are broken down into some number of
|
2006-05-17 18:22:14 +00:00
|
|
|
/// legal first class types. For example, <8 x float> maps to 2 MVT::v4f32
|
2006-03-31 00:28:56 +00:00
|
|
|
/// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack.
|
|
|
|
///
|
|
|
|
/// This method returns the number and type of the resultant breakdown.
|
|
|
|
///
|
2007-02-15 02:26:10 +00:00
|
|
|
unsigned TargetLowering::getVectorTypeBreakdown(const VectorType *PTy,
|
2006-03-31 00:46:36 +00:00
|
|
|
MVT::ValueType &PTyElementVT,
|
|
|
|
MVT::ValueType &PTyLegalElementVT) const {
|
2006-03-31 00:28:56 +00:00
|
|
|
// Figure out the right, legal destination reg to copy into.
|
|
|
|
unsigned NumElts = PTy->getNumElements();
|
|
|
|
MVT::ValueType EltTy = getValueType(PTy->getElementType());
|
|
|
|
|
|
|
|
unsigned NumVectorRegs = 1;
|
|
|
|
|
|
|
|
// 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 && !isTypeLegal(getVectorType(EltTy, NumElts))) {
|
|
|
|
NumElts >>= 1;
|
|
|
|
NumVectorRegs <<= 1;
|
|
|
|
}
|
|
|
|
|
2007-04-12 04:44:28 +00:00
|
|
|
MVT::ValueType VT = getVectorType(EltTy, NumElts);
|
|
|
|
if (!isTypeLegal(VT))
|
2006-03-31 00:28:56 +00:00
|
|
|
VT = EltTy;
|
2006-03-31 01:50:09 +00:00
|
|
|
PTyElementVT = VT;
|
2006-03-31 00:28:56 +00:00
|
|
|
|
|
|
|
MVT::ValueType DestVT = getTypeToTransformTo(VT);
|
2006-03-31 00:46:36 +00:00
|
|
|
PTyLegalElementVT = DestVT;
|
2006-03-31 00:28:56 +00:00
|
|
|
if (DestVT < VT) {
|
|
|
|
// Value is expanded, e.g. i64 -> i16.
|
2006-03-31 00:46:36 +00:00
|
|
|
return NumVectorRegs*(MVT::getSizeInBits(VT)/MVT::getSizeInBits(DestVT));
|
2006-03-31 00:28:56 +00:00
|
|
|
} else {
|
|
|
|
// Otherwise, promotion or legal types use the same number of registers as
|
|
|
|
// the vector decimated to the appropriate level.
|
2006-03-31 00:46:36 +00:00
|
|
|
return NumVectorRegs;
|
2006-03-31 00:28:56 +00:00
|
|
|
}
|
|
|
|
|
2006-05-17 18:10:06 +00:00
|
|
|
return 1;
|
2006-03-31 00:28:56 +00:00
|
|
|
}
|
|
|
|
|
2006-02-04 02:13:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Optimization Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
/// ShrinkDemandedConstant - Check to see if the specified operand of the
|
|
|
|
/// specified instruction is a constant integer. If so, check to see if there
|
|
|
|
/// are any bits set in the constant that are not demanded. If so, shrink the
|
|
|
|
/// constant and return true.
|
|
|
|
bool TargetLowering::TargetLoweringOpt::ShrinkDemandedConstant(SDOperand Op,
|
|
|
|
uint64_t Demanded) {
|
2006-02-26 23:36:02 +00:00
|
|
|
// FIXME: ISD::SELECT, ISD::SELECT_CC
|
2006-02-16 21:11:51 +00:00
|
|
|
switch(Op.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR:
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
|
|
|
|
if ((~Demanded & C->getValue()) != 0) {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
SDOperand New = DAG.getNode(Op.getOpcode(), VT, Op.getOperand(0),
|
|
|
|
DAG.getConstant(Demanded & C->getValue(),
|
|
|
|
VT));
|
|
|
|
return CombineTo(Op, New);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// SimplifyDemandedBits - Look at Op. At this point, we know that only the
|
|
|
|
/// DemandedMask bits of the result of Op are ever used downstream. If we can
|
|
|
|
/// use this information to simplify Op, create a new simplified DAG node and
|
|
|
|
/// return true, returning the original and new nodes in Old and New. Otherwise,
|
|
|
|
/// analyze the expression and return a mask of KnownOne and KnownZero bits for
|
|
|
|
/// the expression (used to simplify the caller). The KnownZero/One bits may
|
|
|
|
/// only be accurate for those bits in the DemandedMask.
|
|
|
|
bool TargetLowering::SimplifyDemandedBits(SDOperand Op, uint64_t DemandedMask,
|
|
|
|
uint64_t &KnownZero,
|
|
|
|
uint64_t &KnownOne,
|
|
|
|
TargetLoweringOpt &TLO,
|
|
|
|
unsigned Depth) const {
|
|
|
|
KnownZero = KnownOne = 0; // Don't know anything.
|
|
|
|
// Other users may use these bits.
|
|
|
|
if (!Op.Val->hasOneUse()) {
|
|
|
|
if (Depth != 0) {
|
|
|
|
// If not at the root, Just compute the KnownZero/KnownOne bits to
|
|
|
|
// simplify things downstream.
|
|
|
|
ComputeMaskedBits(Op, DemandedMask, KnownZero, KnownOne, Depth);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// If this is the root being simplified, allow it to have multiple uses,
|
|
|
|
// just set the DemandedMask to all bits.
|
|
|
|
DemandedMask = MVT::getIntVTBitMask(Op.getValueType());
|
|
|
|
} else if (DemandedMask == 0) {
|
|
|
|
// Not demanding any bits from Op.
|
|
|
|
if (Op.getOpcode() != ISD::UNDEF)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::UNDEF, Op.getValueType()));
|
2006-02-03 22:24:05 +00:00
|
|
|
return false;
|
2006-02-16 21:11:51 +00:00
|
|
|
} else if (Depth == 6) { // Limit search depth.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut;
|
2006-02-03 22:24:05 +00:00
|
|
|
switch (Op.getOpcode()) {
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::Constant:
|
|
|
|
// We know all of the bits for a constant!
|
|
|
|
KnownOne = cast<ConstantSDNode>(Op)->getValue() & DemandedMask;
|
|
|
|
KnownZero = ~KnownOne & DemandedMask;
|
2006-02-26 23:36:02 +00:00
|
|
|
return false; // Don't fall through, will infinitely loop.
|
2006-02-03 22:24:05 +00:00
|
|
|
case ISD::AND:
|
2006-02-27 00:36:27 +00:00
|
|
|
// If the RHS is a constant, check to see if the LHS would be zero without
|
|
|
|
// using the bits from the RHS. Below, we use knowledge about the RHS to
|
|
|
|
// simplify the LHS, here we're using information from the LHS to simplify
|
|
|
|
// the RHS.
|
|
|
|
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
uint64_t LHSZero, LHSOne;
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), DemandedMask,
|
|
|
|
LHSZero, LHSOne, Depth+1);
|
|
|
|
// If the LHS already has zeros where RHSC does, this and is dead.
|
|
|
|
if ((LHSZero & DemandedMask) == (~RHSC->getValue() & DemandedMask))
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
// If any of the set bits in the RHS are known zero on the LHS, shrink
|
|
|
|
// the constant.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & DemandedMask))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), DemandedMask, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask & ~KnownZero,
|
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known one on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'and'.
|
|
|
|
if ((DemandedMask & ~KnownZero2 & KnownOne)==(DemandedMask & ~KnownZero2))
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
if ((DemandedMask & ~KnownZero & KnownOne2)==(DemandedMask & ~KnownZero))
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If all of the demanded bits in the inputs are known zeros, return zero.
|
|
|
|
if ((DemandedMask & (KnownZero|KnownZero2)) == DemandedMask)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getConstant(0, Op.getValueType()));
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, DemandedMask & ~KnownZero2))
|
|
|
|
return true;
|
Just like we use the RHS of an AND to simplify the LHS, use the LHS to
simplify the RHS. This allows for the elimination of many thousands of
ands from multisource, and compiles CodeGen/PowerPC/and-elim.ll:test2
into this:
_test2:
srwi r2, r3, 1
xori r3, r2, 40961
blr
instead of this:
_test2:
rlwinm r2, r3, 31, 17, 31
xori r2, r2, 40961
rlwinm r3, r2, 0, 16, 31
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26388 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-27 00:22:28 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// Output known-1 bits are only known if set in both the LHS & RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
|
|
|
KnownZero |= KnownZero2;
|
|
|
|
break;
|
|
|
|
case ISD::OR:
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), DemandedMask, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask & ~KnownOne,
|
|
|
|
KnownZero2, KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'or'.
|
2006-02-17 02:12:18 +00:00
|
|
|
if ((DemandedMask & ~KnownOne2 & KnownZero) == (DemandedMask & ~KnownOne2))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
2006-02-17 02:12:18 +00:00
|
|
|
if ((DemandedMask & ~KnownOne & KnownZero2) == (DemandedMask & ~KnownOne))
|
2006-02-16 21:11:51 +00:00
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If all of the potentially set bits on one side are known to be set on
|
|
|
|
// the other side, just use the 'other' side.
|
|
|
|
if ((DemandedMask & (~KnownZero) & KnownOne2) ==
|
|
|
|
(DemandedMask & (~KnownZero)))
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
if ((DemandedMask & (~KnownZero2) & KnownOne) ==
|
|
|
|
(DemandedMask & (~KnownZero2)))
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, DemandedMask))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
// Output known-1 are known to be set if set in either the LHS | RHS.
|
|
|
|
KnownOne |= KnownOne2;
|
|
|
|
break;
|
|
|
|
case ISD::XOR:
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), DemandedMask, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask, KnownZero2,
|
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'xor'.
|
|
|
|
if ((DemandedMask & KnownZero) == DemandedMask)
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
if ((DemandedMask & KnownZero2) == DemandedMask)
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(1));
|
2006-11-27 21:50:02 +00:00
|
|
|
|
|
|
|
// If all of the unknown bits are known to be zero on one side or the other
|
|
|
|
// (but not both) turn this into an *inclusive* or.
|
|
|
|
// e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
|
|
|
|
if ((DemandedMask & ~KnownZero & ~KnownZero2) == 0)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, Op.getValueType(),
|
|
|
|
Op.getOperand(0),
|
|
|
|
Op.getOperand(1)));
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
|
|
|
KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
|
|
|
|
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
|
|
|
KnownOneOut = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
|
|
|
|
|
|
|
|
// If all of the demanded bits on one side are known, and all of the set
|
|
|
|
// bits on that side are also known to be set on the other side, turn this
|
|
|
|
// into an AND, as we know the bits will be cleared.
|
|
|
|
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
|
|
|
|
if ((DemandedMask & (KnownZero|KnownOne)) == DemandedMask) { // all known
|
|
|
|
if ((KnownOne & KnownOne2) == KnownOne) {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
SDOperand ANDC = TLO.DAG.getConstant(~KnownOne & DemandedMask, VT);
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, VT, Op.getOperand(0),
|
|
|
|
ANDC));
|
|
|
|
}
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
|
|
|
// FIXME: for XOR, we prefer to force bits to 1 if they will make a -1.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, DemandedMask))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
KnownOne = KnownOneOut;
|
|
|
|
break;
|
|
|
|
case ISD::SETCC:
|
|
|
|
// If we know the result of a setcc has the top bits zero, use this info.
|
|
|
|
if (getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult)
|
|
|
|
KnownZero |= (MVT::getIntVTBitMask(Op.getValueType()) ^ 1ULL);
|
|
|
|
break;
|
|
|
|
case ISD::SELECT:
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), DemandedMask, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(1), DemandedMask, KnownZero2,
|
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the operands are constants, see if we can simplify them.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, DemandedMask))
|
|
|
|
return true;
|
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
break;
|
|
|
|
case ISD::SELECT_CC:
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(3), DemandedMask, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(2), DemandedMask, KnownZero2,
|
|
|
|
KnownOne2, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the operands are constants, see if we can simplify them.
|
|
|
|
if (TLO.ShrinkDemandedConstant(Op, DemandedMask))
|
|
|
|
return true;
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
2006-02-03 22:24:05 +00:00
|
|
|
break;
|
|
|
|
case ISD::SHL:
|
2006-02-16 21:11:51 +00:00
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
unsigned ShAmt = SA->getValue();
|
|
|
|
SDOperand InOp = Op.getOperand(0);
|
|
|
|
|
|
|
|
// 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))) {
|
|
|
|
if (ShAmt && (DemandedMask & ((1ULL << ShAmt)-1)) == 0) {
|
|
|
|
unsigned C1 = cast<ConstantSDNode>(InOp.getOperand(1))->getValue();
|
|
|
|
unsigned Opc = ISD::SHL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SRL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDOperand NewSA =
|
2007-04-17 22:53:02 +00:00
|
|
|
TLO.DAG.getConstant(ShAmt-C1, Op.getOperand(1).getValueType());
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, VT,
|
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask >> ShAmt,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
KnownZero <<= SA->getValue();
|
|
|
|
KnownOne <<= SA->getValue();
|
|
|
|
KnownZero |= (1ULL << SA->getValue())-1; // low bits known zero.
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRL:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned ShAmt = SA->getValue();
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
uint64_t TypeMask = MVT::getIntVTBitMask(VT);
|
|
|
|
unsigned VTSize = MVT::getSizeInBits(VT);
|
|
|
|
SDOperand InOp = Op.getOperand(0);
|
|
|
|
|
|
|
|
// 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))) {
|
|
|
|
if (ShAmt && (DemandedMask & (~0ULL << (VTSize-ShAmt))) == 0) {
|
|
|
|
unsigned C1 = cast<ConstantSDNode>(InOp.getOperand(1))->getValue();
|
|
|
|
unsigned Opc = ISD::SRL;
|
|
|
|
int Diff = ShAmt-C1;
|
|
|
|
if (Diff < 0) {
|
|
|
|
Diff = -Diff;
|
|
|
|
Opc = ISD::SHL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDOperand NewSA =
|
2007-04-17 22:53:02 +00:00
|
|
|
TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, VT,
|
|
|
|
InOp.getOperand(0), NewSA));
|
|
|
|
}
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Compute the new bits that are at the top now.
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
if (SimplifyDemandedBits(InOp, (DemandedMask << ShAmt) & TypeMask,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
|
|
|
KnownZero >>= ShAmt;
|
|
|
|
KnownOne >>= ShAmt;
|
2006-06-13 16:52:37 +00:00
|
|
|
|
|
|
|
uint64_t HighBits = (1ULL << ShAmt)-1;
|
Fold (x << c1)>> c2 into a single shift if the bits shifted out aren't used.
This compiles:
int baz(long long a) { return (short)(((int)(a >>24)) >> 9); }
into:
_baz:
srwi r2, r3, 1
extsh r3, r2
blr
on PPC, instead of:
_baz:
slwi r2, r3, 8
srwi r2, r2, 9
extsh r3, r2
blr
GCC produces:
_baz:
srwi r10,r4,24
insrwi r10,r3,24,0
srawi r9,r3,24
srawi r3,r10,9
extsh r3,r3
blr
This implements CodeGen/PowerPC/shl_elim.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36221 91177308-0d34-0410-b5e6-96231b3b80d8
2007-04-17 21:14:16 +00:00
|
|
|
HighBits <<= VTSize - ShAmt;
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero |= HighBits; // High bits known zero.
|
2006-02-16 21:11:51 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SRA:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned ShAmt = SA->getValue();
|
|
|
|
|
|
|
|
// Compute the new bits that are at the top now.
|
|
|
|
uint64_t TypeMask = MVT::getIntVTBitMask(VT);
|
|
|
|
|
2006-05-08 17:22:53 +00:00
|
|
|
uint64_t InDemandedMask = (DemandedMask << ShAmt) & TypeMask;
|
|
|
|
|
|
|
|
// If any of the demanded bits are produced by the sign extension, we also
|
|
|
|
// demand the input sign bit.
|
2006-06-13 16:52:37 +00:00
|
|
|
uint64_t HighBits = (1ULL << ShAmt)-1;
|
|
|
|
HighBits <<= MVT::getSizeInBits(VT) - ShAmt;
|
2006-05-08 17:22:53 +00:00
|
|
|
if (HighBits & DemandedMask)
|
|
|
|
InDemandedMask |= MVT::getIntVTSignBit(VT);
|
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask,
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero >>= ShAmt;
|
|
|
|
KnownOne >>= ShAmt;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Handle the sign bits.
|
|
|
|
uint64_t SignBit = MVT::getIntVTSignBit(VT);
|
2006-06-13 16:52:37 +00:00
|
|
|
SignBit >>= ShAmt; // Adjust to where it is now in the mask.
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// If the input sign bit is known to be zero, or if none of the top bits
|
|
|
|
// are demanded, turn this into an unsigned shift right.
|
|
|
|
if ((KnownZero & SignBit) || (HighBits & ~DemandedMask) == HighBits) {
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, VT, Op.getOperand(0),
|
|
|
|
Op.getOperand(1)));
|
|
|
|
} else if (KnownOne & SignBit) { // New bits are known one.
|
|
|
|
KnownOne |= HighBits;
|
|
|
|
}
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
|
|
|
MVT::ValueType EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Sign extension. Compute the demanded bits in the result that are not
|
2006-02-16 21:11:51 +00:00
|
|
|
// present in the input.
|
2006-02-26 23:36:02 +00:00
|
|
|
uint64_t NewBits = ~MVT::getIntVTBitMask(EVT) & DemandedMask;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// If none of the extended bits are demanded, eliminate the sextinreg.
|
|
|
|
if (NewBits == 0)
|
|
|
|
return TLO.CombineTo(Op, Op.getOperand(0));
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
uint64_t InSignBit = MVT::getIntVTSignBit(EVT);
|
|
|
|
int64_t InputDemandedBits = DemandedMask & MVT::getIntVTBitMask(EVT);
|
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// Since the sign extended bits are demanded, we know that the sign
|
2006-02-16 21:11:51 +00:00
|
|
|
// bit is demanded.
|
2006-02-26 23:36:02 +00:00
|
|
|
InputDemandedBits |= InSignBit;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
2006-02-03 22:24:05 +00:00
|
|
|
return true;
|
2006-02-16 21:11:51 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
|
|
|
|
2006-02-26 23:36:02 +00:00
|
|
|
// If the input sign bit is known zero, convert this into a zero extension.
|
|
|
|
if (KnownZero & InSignBit)
|
|
|
|
return TLO.CombineTo(Op,
|
|
|
|
TLO.DAG.getZeroExtendInReg(Op.getOperand(0), EVT));
|
|
|
|
|
|
|
|
if (KnownOne & InSignBit) { // Input sign bit known set
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
2006-02-26 23:36:02 +00:00
|
|
|
} else { // Input sign bit unknown
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTPOP: {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned LowBits = Log2_32(MVT::getSizeInBits(VT))+1;
|
|
|
|
KnownZero = ~((1ULL << LowBits)-1) & MVT::getIntVTBitMask(VT);
|
|
|
|
KnownOne = 0;
|
|
|
|
break;
|
|
|
|
}
|
2006-10-09 20:57:25 +00:00
|
|
|
case ISD::LOAD: {
|
2006-10-04 00:56:09 +00:00
|
|
|
if (ISD::isZEXTLoad(Op.Val)) {
|
2006-10-09 20:57:25 +00:00
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
2006-10-11 07:10:22 +00:00
|
|
|
MVT::ValueType VT = LD->getLoadedVT();
|
2006-10-04 00:56:09 +00:00
|
|
|
KnownZero |= ~MVT::getIntVTBitMask(VT) & DemandedMask;
|
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::ZERO_EXTEND: {
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(Op.getOperand(0).getValueType());
|
|
|
|
|
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
|
|
|
uint64_t NewBits = (~InMask) & DemandedMask;
|
|
|
|
if (NewBits == 0)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ANY_EXTEND,
|
|
|
|
Op.getValueType(),
|
|
|
|
Op.getOperand(0)));
|
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask & InMask,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero |= NewBits;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::SIGN_EXTEND: {
|
|
|
|
MVT::ValueType InVT = Op.getOperand(0).getValueType();
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(InVT);
|
|
|
|
uint64_t InSignBit = MVT::getIntVTSignBit(InVT);
|
|
|
|
uint64_t NewBits = (~InMask) & DemandedMask;
|
|
|
|
|
|
|
|
// If none of the top bits are demanded, convert this into an any_extend.
|
|
|
|
if (NewBits == 0)
|
2007-02-01 04:55:59 +00:00
|
|
|
return TLO.CombineTo(Op,TLO.DAG.getNode(ISD::ANY_EXTEND,Op.getValueType(),
|
2006-02-26 23:36:02 +00:00
|
|
|
Op.getOperand(0)));
|
|
|
|
|
|
|
|
// Since some of the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
|
|
|
uint64_t InDemandedBits = DemandedMask & InMask;
|
|
|
|
InDemandedBits |= InSignBit;
|
|
|
|
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedBits, KnownZero,
|
|
|
|
KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// If the sign bit is known zero, convert this to a zero extend.
|
|
|
|
if (KnownZero & InSignBit)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ZERO_EXTEND,
|
|
|
|
Op.getValueType(),
|
|
|
|
Op.getOperand(0)));
|
|
|
|
|
|
|
|
// If the sign bit is known one, the top bits match.
|
|
|
|
if (KnownOne & InSignBit) {
|
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Otherwise, top bits aren't known.
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::ANY_EXTEND: {
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(Op.getOperand(0).getValueType());
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask & InMask,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
break;
|
|
|
|
}
|
2006-05-05 22:32:12 +00:00
|
|
|
case ISD::TRUNCATE: {
|
2006-05-06 00:11:52 +00:00
|
|
|
// Simplify the input, using demanded bit information, and compute the known
|
|
|
|
// zero/one bits live out.
|
2006-05-05 22:32:12 +00:00
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
2006-05-06 00:11:52 +00:00
|
|
|
|
|
|
|
// If the input is only used by this truncate, see if we can shrink it based
|
|
|
|
// on the known demanded bits.
|
|
|
|
if (Op.getOperand(0).Val->hasOneUse()) {
|
|
|
|
SDOperand In = Op.getOperand(0);
|
|
|
|
switch (In.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::SRL:
|
|
|
|
// Shrink SRL by a constant if none of the high bits shifted in are
|
|
|
|
// demanded.
|
|
|
|
if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(In.getOperand(1))){
|
|
|
|
uint64_t HighBits = MVT::getIntVTBitMask(In.getValueType());
|
|
|
|
HighBits &= ~MVT::getIntVTBitMask(Op.getValueType());
|
|
|
|
HighBits >>= ShAmt->getValue();
|
|
|
|
|
|
|
|
if (ShAmt->getValue() < MVT::getSizeInBits(Op.getValueType()) &&
|
|
|
|
(DemandedMask & HighBits) == 0) {
|
|
|
|
// None of the shifted in bits are needed. Add a truncate of the
|
|
|
|
// shift input, then shift it.
|
|
|
|
SDOperand NewTrunc = TLO.DAG.getNode(ISD::TRUNCATE,
|
|
|
|
Op.getValueType(),
|
|
|
|
In.getOperand(0));
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL,Op.getValueType(),
|
|
|
|
NewTrunc, In.getOperand(1)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-05 22:32:12 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
uint64_t OutMask = MVT::getIntVTBitMask(Op.getValueType());
|
|
|
|
KnownZero &= OutMask;
|
|
|
|
KnownOne &= OutMask;
|
|
|
|
break;
|
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
case ISD::AssertZext: {
|
|
|
|
MVT::ValueType VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(VT);
|
|
|
|
if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask & InMask,
|
|
|
|
KnownZero, KnownOne, TLO, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero |= ~InMask & DemandedMask;
|
|
|
|
break;
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::ADD:
|
2006-02-27 01:00:42 +00:00
|
|
|
case ISD::SUB:
|
2006-04-02 06:15:09 +00:00
|
|
|
case ISD::INTRINSIC_WO_CHAIN:
|
|
|
|
case ISD::INTRINSIC_W_CHAIN:
|
|
|
|
case ISD::INTRINSIC_VOID:
|
|
|
|
// Just use ComputeMaskedBits to compute output bits.
|
2006-02-27 01:00:42 +00:00
|
|
|
ComputeMaskedBits(Op, DemandedMask, KnownZero, KnownOne, Depth);
|
|
|
|
break;
|
2006-02-03 22:24:05 +00:00
|
|
|
}
|
2006-02-26 23:36:02 +00:00
|
|
|
|
|
|
|
// If we know the value of all of the demanded bits, return this as a
|
|
|
|
// constant.
|
|
|
|
if ((DemandedMask & (KnownZero|KnownOne)) == DemandedMask)
|
|
|
|
return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType()));
|
|
|
|
|
2006-02-03 22:24:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
2006-01-30 04:09:27 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
|
|
|
|
/// this predicate to simplify operations downstream. Mask is known to be zero
|
|
|
|
/// for bits that V cannot have.
|
|
|
|
bool TargetLowering::MaskedValueIsZero(SDOperand Op, uint64_t Mask,
|
|
|
|
unsigned Depth) const {
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
return (KnownZero & Mask) == Mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ComputeMaskedBits - Determine which of the bits specified in Mask are
|
|
|
|
/// known to be either zero or one and return them in the KnownZero/KnownOne
|
|
|
|
/// bitsets. This code only analyzes bits in Mask, in order to short-circuit
|
|
|
|
/// processing.
|
|
|
|
void TargetLowering::ComputeMaskedBits(SDOperand Op, uint64_t Mask,
|
|
|
|
uint64_t &KnownZero, uint64_t &KnownOne,
|
|
|
|
unsigned Depth) const {
|
|
|
|
KnownZero = KnownOne = 0; // Don't know anything.
|
|
|
|
if (Depth == 6 || Mask == 0)
|
|
|
|
return; // Limit search depth.
|
2006-01-30 04:09:27 +00:00
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
uint64_t KnownZero2, KnownOne2;
|
|
|
|
|
2006-01-30 04:09:27 +00:00
|
|
|
switch (Op.getOpcode()) {
|
|
|
|
case ISD::Constant:
|
2006-02-16 21:11:51 +00:00
|
|
|
// We know all of the bits for a constant!
|
|
|
|
KnownOne = cast<ConstantSDNode>(Op)->getValue() & Mask;
|
|
|
|
KnownZero = ~KnownOne & Mask;
|
|
|
|
return;
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::AND:
|
2006-02-16 21:11:51 +00:00
|
|
|
// If either the LHS or the RHS are Zero, the result is zero.
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
Mask &= ~KnownZero;
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
return;
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::OR:
|
2006-02-16 21:11:51 +00:00
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
Mask &= ~KnownOne;
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
return;
|
|
|
|
case ISD::XOR: {
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
|
|
|
uint64_t KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
|
|
|
|
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
|
|
|
KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
|
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
return;
|
|
|
|
}
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::SELECT:
|
2006-02-16 21:11:51 +00:00
|
|
|
ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
return;
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::SELECT_CC:
|
2006-02-16 21:11:51 +00:00
|
|
|
ComputeMaskedBits(Op.getOperand(3), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
return;
|
|
|
|
case ISD::SETCC:
|
|
|
|
// If we know the result of a setcc has the top bits zero, use this info.
|
|
|
|
if (getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult)
|
|
|
|
KnownZero |= (MVT::getIntVTBitMask(Op.getValueType()) ^ 1ULL);
|
|
|
|
return;
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::SHL:
|
2006-02-16 21:11:51 +00:00
|
|
|
// (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2006-06-13 16:52:37 +00:00
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask >> SA->getValue(),
|
|
|
|
KnownZero, KnownOne, Depth+1);
|
2006-02-16 21:11:51 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero <<= SA->getValue();
|
|
|
|
KnownOne <<= SA->getValue();
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero |= (1ULL << SA->getValue())-1; // low bits known zero.
|
2006-01-30 04:09:27 +00:00
|
|
|
}
|
2006-02-18 02:43:25 +00:00
|
|
|
return;
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::SRL:
|
|
|
|
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2006-06-13 16:52:37 +00:00
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned ShAmt = SA->getValue();
|
|
|
|
|
|
|
|
uint64_t TypeMask = MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), (Mask << ShAmt) & TypeMask,
|
|
|
|
KnownZero, KnownOne, Depth+1);
|
2006-02-18 02:43:25 +00:00
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
|
|
|
KnownZero >>= ShAmt;
|
|
|
|
KnownOne >>= ShAmt;
|
|
|
|
|
|
|
|
uint64_t HighBits = (1ULL << ShAmt)-1;
|
|
|
|
HighBits <<= MVT::getSizeInBits(VT)-ShAmt;
|
|
|
|
KnownZero |= HighBits; // High bits known zero.
|
2006-01-30 04:09:27 +00:00
|
|
|
}
|
2006-02-18 02:43:25 +00:00
|
|
|
return;
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::SRA:
|
|
|
|
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
2006-06-13 16:52:37 +00:00
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned ShAmt = SA->getValue();
|
|
|
|
|
|
|
|
// Compute the new bits that are at the top now.
|
|
|
|
uint64_t TypeMask = MVT::getIntVTBitMask(VT);
|
|
|
|
|
|
|
|
uint64_t InDemandedMask = (Mask << ShAmt) & TypeMask;
|
|
|
|
// If any of the demanded bits are produced by the sign extension, we also
|
|
|
|
// demand the input sign bit.
|
|
|
|
uint64_t HighBits = (1ULL << ShAmt)-1;
|
|
|
|
HighBits <<= MVT::getSizeInBits(VT) - ShAmt;
|
|
|
|
if (HighBits & Mask)
|
|
|
|
InDemandedMask |= MVT::getIntVTSignBit(VT);
|
|
|
|
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), InDemandedMask, KnownZero, KnownOne,
|
|
|
|
Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
|
|
|
KnownZero >>= ShAmt;
|
|
|
|
KnownOne >>= ShAmt;
|
2006-02-16 21:11:51 +00:00
|
|
|
|
|
|
|
// Handle the sign bits.
|
2006-06-13 16:52:37 +00:00
|
|
|
uint64_t SignBit = MVT::getIntVTSignBit(VT);
|
|
|
|
SignBit >>= ShAmt; // Adjust to where it is now in the mask.
|
2006-02-16 21:11:51 +00:00
|
|
|
|
2006-06-13 13:08:58 +00:00
|
|
|
if (KnownZero & SignBit) {
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownZero |= HighBits; // New bits are known zero.
|
2006-06-13 13:08:58 +00:00
|
|
|
} else if (KnownOne & SignBit) {
|
2006-06-13 16:52:37 +00:00
|
|
|
KnownOne |= HighBits; // New bits are known one.
|
2006-01-30 04:09:27 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-18 02:43:25 +00:00
|
|
|
return;
|
2006-02-26 23:36:02 +00:00
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
|
|
|
MVT::ValueType EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
|
|
|
|
|
|
|
// Sign extension. Compute the demanded bits in the result that are not
|
|
|
|
// present in the input.
|
|
|
|
uint64_t NewBits = ~MVT::getIntVTBitMask(EVT) & Mask;
|
|
|
|
|
|
|
|
uint64_t InSignBit = MVT::getIntVTSignBit(EVT);
|
|
|
|
int64_t InputDemandedBits = Mask & MVT::getIntVTBitMask(EVT);
|
|
|
|
|
|
|
|
// If the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
|
|
|
if (NewBits)
|
|
|
|
InputDemandedBits |= InSignBit;
|
|
|
|
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), InputDemandedBits,
|
|
|
|
KnownZero, KnownOne, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
|
|
|
if (KnownZero & InSignBit) { // Input sign bit known clear
|
|
|
|
KnownZero |= NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
} else if (KnownOne & InSignBit) { // Input sign bit known set
|
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Input sign bit unknown
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2006-01-30 04:09:27 +00:00
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTLZ:
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::CTPOP: {
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
unsigned LowBits = Log2_32(MVT::getSizeInBits(VT))+1;
|
|
|
|
KnownZero = ~((1ULL << LowBits)-1) & MVT::getIntVTBitMask(VT);
|
|
|
|
KnownOne = 0;
|
|
|
|
return;
|
|
|
|
}
|
2006-10-09 20:57:25 +00:00
|
|
|
case ISD::LOAD: {
|
2006-10-04 00:56:09 +00:00
|
|
|
if (ISD::isZEXTLoad(Op.Val)) {
|
2006-10-09 20:57:25 +00:00
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
2006-10-11 07:10:22 +00:00
|
|
|
MVT::ValueType VT = LD->getLoadedVT();
|
2006-10-04 00:56:09 +00:00
|
|
|
KnownZero |= ~MVT::getIntVTBitMask(VT) & Mask;
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case ISD::ZERO_EXTEND: {
|
2006-02-26 23:36:02 +00:00
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(Op.getOperand(0).getValueType());
|
|
|
|
uint64_t NewBits = (~InMask) & Mask;
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask & InMask, KnownZero,
|
|
|
|
KnownOne, Depth+1);
|
|
|
|
KnownZero |= NewBits & Mask;
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case ISD::SIGN_EXTEND: {
|
|
|
|
MVT::ValueType InVT = Op.getOperand(0).getValueType();
|
|
|
|
unsigned InBits = MVT::getSizeInBits(InVT);
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(InVT);
|
|
|
|
uint64_t InSignBit = 1ULL << (InBits-1);
|
|
|
|
uint64_t NewBits = (~InMask) & Mask;
|
|
|
|
uint64_t InDemandedBits = Mask & InMask;
|
|
|
|
|
|
|
|
// If any of the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
|
|
|
if (NewBits & Mask)
|
|
|
|
InDemandedBits |= InSignBit;
|
|
|
|
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), InDemandedBits, KnownZero,
|
|
|
|
KnownOne, Depth+1);
|
|
|
|
// If the sign bit is known zero or one, the top bits match.
|
|
|
|
if (KnownZero & InSignBit) {
|
|
|
|
KnownZero |= NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
} else if (KnownOne & InSignBit) {
|
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Otherwise, top bits aren't known.
|
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case ISD::ANY_EXTEND: {
|
2006-02-26 23:36:02 +00:00
|
|
|
MVT::ValueType VT = Op.getOperand(0).getValueType();
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask & MVT::getIntVTBitMask(VT),
|
|
|
|
KnownZero, KnownOne, Depth+1);
|
2006-02-16 21:11:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-05-05 22:32:12 +00:00
|
|
|
case ISD::TRUNCATE: {
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
uint64_t OutMask = MVT::getIntVTBitMask(Op.getValueType());
|
|
|
|
KnownZero &= OutMask;
|
|
|
|
KnownOne &= OutMask;
|
|
|
|
break;
|
|
|
|
}
|
2006-02-16 21:11:51 +00:00
|
|
|
case ISD::AssertZext: {
|
2006-02-26 23:36:02 +00:00
|
|
|
MVT::ValueType VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
|
|
|
uint64_t InMask = MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask & InMask, KnownZero,
|
|
|
|
KnownOne, Depth+1);
|
|
|
|
KnownZero |= (~InMask) & Mask;
|
2006-02-16 21:11:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case ISD::ADD: {
|
|
|
|
// If either the LHS or the RHS are Zero, the result is zero.
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the low clear bits
|
2006-03-13 06:42:16 +00:00
|
|
|
// common to both LHS & RHS. For example, 8+(X<<3) is known to have the
|
|
|
|
// low 3 bits clear.
|
2006-02-16 21:11:51 +00:00
|
|
|
uint64_t KnownZeroOut = std::min(CountTrailingZeros_64(~KnownZero),
|
|
|
|
CountTrailingZeros_64(~KnownZero2));
|
|
|
|
|
|
|
|
KnownZero = (1ULL << KnownZeroOut) - 1;
|
|
|
|
KnownOne = 0;
|
|
|
|
return;
|
|
|
|
}
|
2006-02-27 01:00:42 +00:00
|
|
|
case ISD::SUB: {
|
|
|
|
ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(Op.getOperand(0));
|
|
|
|
if (!CLHS) return;
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
// We know that the top bits of C-X are clear if X contains less bits
|
|
|
|
// than C (i.e. no wrap-around can happen). For example, 20-X is
|
2006-02-27 01:00:42 +00:00
|
|
|
// positive if we can prove that X is >= 0 and < 16.
|
|
|
|
MVT::ValueType VT = CLHS->getValueType(0);
|
|
|
|
if ((CLHS->getValue() & MVT::getIntVTSignBit(VT)) == 0) { // sign bit clear
|
|
|
|
unsigned NLZ = CountLeadingZeros_64(CLHS->getValue()+1);
|
|
|
|
uint64_t MaskV = (1ULL << (63-NLZ))-1; // NLZ can't be 64 with no sign bit
|
|
|
|
MaskV = ~MaskV & MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), MaskV, KnownZero, KnownOne, Depth+1);
|
|
|
|
|
|
|
|
// If all of the MaskV bits are known to be zero, then we know the output
|
|
|
|
// top bits are zero, because we now know that the output is from [0-C].
|
|
|
|
if ((KnownZero & MaskV) == MaskV) {
|
|
|
|
unsigned NLZ2 = CountLeadingZeros_64(CLHS->getValue());
|
|
|
|
KnownZero = ~((1ULL << (64-NLZ2))-1) & Mask; // Top bits known zero.
|
|
|
|
KnownOne = 0; // No one bits known.
|
|
|
|
} else {
|
2006-07-07 21:37:21 +00:00
|
|
|
KnownZero = KnownOne = 0; // Otherwise, nothing known.
|
2006-02-27 01:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-18 02:43:25 +00:00
|
|
|
return;
|
2006-02-27 01:00:42 +00:00
|
|
|
}
|
2006-01-30 04:09:27 +00:00
|
|
|
default:
|
|
|
|
// Allow the target to implement this method for its nodes.
|
2006-04-02 06:15:09 +00:00
|
|
|
if (Op.getOpcode() >= ISD::BUILTIN_OP_END) {
|
|
|
|
case ISD::INTRINSIC_WO_CHAIN:
|
|
|
|
case ISD::INTRINSIC_W_CHAIN:
|
|
|
|
case ISD::INTRINSIC_VOID:
|
2006-02-16 21:11:51 +00:00
|
|
|
computeMaskedBitsForTargetNode(Op, Mask, KnownZero, KnownOne);
|
2006-04-02 06:15:09 +00:00
|
|
|
}
|
2006-02-18 02:43:25 +00:00
|
|
|
return;
|
2006-01-30 04:09:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 21:11:51 +00:00
|
|
|
/// computeMaskedBitsForTargetNode - Determine which of the bits specified
|
|
|
|
/// in Mask are known to be either zero or one and return them in the
|
|
|
|
/// KnownZero/KnownOne bitsets.
|
|
|
|
void TargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
|
|
|
|
uint64_t Mask,
|
|
|
|
uint64_t &KnownZero,
|
|
|
|
uint64_t &KnownOne,
|
|
|
|
unsigned Depth) const {
|
2006-04-02 06:19:46 +00:00
|
|
|
assert((Op.getOpcode() >= ISD::BUILTIN_OP_END ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
|
2006-01-30 04:09:27 +00:00
|
|
|
"Should use MaskedValueIsZero if you don't know whether Op"
|
|
|
|
" is a target node!");
|
2006-02-16 21:11:51 +00:00
|
|
|
KnownZero = 0;
|
|
|
|
KnownOne = 0;
|
2005-12-21 23:05:39 +00:00
|
|
|
}
|
2006-01-26 20:37:03 +00:00
|
|
|
|
2006-05-06 09:27:13 +00:00
|
|
|
/// ComputeNumSignBits - Return the number of times the sign bit of the
|
|
|
|
/// register is replicated into the other bits. We know that at least 1 bit
|
|
|
|
/// is always equal to the sign bit (itself), but other cases can give us
|
|
|
|
/// information. For example, immediately after an "SRA X, 2", we know that
|
|
|
|
/// the top 3 bits are all equal to each other, so we return 3.
|
|
|
|
unsigned TargetLowering::ComputeNumSignBits(SDOperand Op, unsigned Depth) const{
|
|
|
|
MVT::ValueType VT = Op.getValueType();
|
|
|
|
assert(MVT::isInteger(VT) && "Invalid VT!");
|
|
|
|
unsigned VTBits = MVT::getSizeInBits(VT);
|
|
|
|
unsigned Tmp, Tmp2;
|
|
|
|
|
|
|
|
if (Depth == 6)
|
|
|
|
return 1; // Limit search depth.
|
|
|
|
|
|
|
|
switch (Op.getOpcode()) {
|
2006-05-06 22:39:59 +00:00
|
|
|
default: break;
|
2006-05-06 09:27:13 +00:00
|
|
|
case ISD::AssertSext:
|
|
|
|
Tmp = MVT::getSizeInBits(cast<VTSDNode>(Op.getOperand(1))->getVT());
|
|
|
|
return VTBits-Tmp+1;
|
|
|
|
case ISD::AssertZext:
|
|
|
|
Tmp = MVT::getSizeInBits(cast<VTSDNode>(Op.getOperand(1))->getVT());
|
|
|
|
return VTBits-Tmp;
|
2006-05-06 22:39:59 +00:00
|
|
|
|
|
|
|
case ISD::Constant: {
|
|
|
|
uint64_t Val = cast<ConstantSDNode>(Op)->getValue();
|
|
|
|
// If negative, invert the bits, then look at it.
|
|
|
|
if (Val & MVT::getIntVTSignBit(VT))
|
|
|
|
Val = ~Val;
|
|
|
|
|
|
|
|
// Shift the bits so they are the leading bits in the int64_t.
|
|
|
|
Val <<= 64-VTBits;
|
|
|
|
|
|
|
|
// Return # leading zeros. We use 'min' here in case Val was zero before
|
|
|
|
// shifting. We don't want to return '64' as for an i32 "0".
|
|
|
|
return std::min(VTBits, CountLeadingZeros_64(Val));
|
|
|
|
}
|
|
|
|
|
|
|
|
case ISD::SIGN_EXTEND:
|
|
|
|
Tmp = VTBits-MVT::getSizeInBits(Op.getOperand(0).getValueType());
|
|
|
|
return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp;
|
|
|
|
|
2006-05-06 09:27:13 +00:00
|
|
|
case ISD::SIGN_EXTEND_INREG:
|
|
|
|
// Max of the input and what this extends.
|
|
|
|
Tmp = MVT::getSizeInBits(cast<VTSDNode>(Op.getOperand(1))->getVT());
|
|
|
|
Tmp = VTBits-Tmp+1;
|
|
|
|
|
|
|
|
Tmp2 = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
return std::max(Tmp, Tmp2);
|
|
|
|
|
|
|
|
case ISD::SRA:
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
// SRA X, C -> adds C sign bits.
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
Tmp += C->getValue();
|
|
|
|
if (Tmp > VTBits) Tmp = VTBits;
|
|
|
|
}
|
|
|
|
return Tmp;
|
2006-05-06 22:39:59 +00:00
|
|
|
case ISD::SHL:
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
// shl destroys sign bits.
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (C->getValue() >= VTBits || // Bad shift.
|
|
|
|
C->getValue() >= Tmp) break; // Shifted all sign bits out.
|
|
|
|
return Tmp - C->getValue();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR: // NOT is handled here.
|
|
|
|
// Logical binary ops preserve the number of sign bits.
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (Tmp == 1) return 1; // Early out.
|
|
|
|
Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1);
|
|
|
|
return std::min(Tmp, Tmp2);
|
|
|
|
|
|
|
|
case ISD::SELECT:
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (Tmp == 1) return 1; // Early out.
|
|
|
|
Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1);
|
|
|
|
return std::min(Tmp, Tmp2);
|
|
|
|
|
|
|
|
case ISD::SETCC:
|
|
|
|
// If setcc returns 0/-1, all bits are sign bits.
|
|
|
|
if (getSetCCResultContents() == ZeroOrNegativeOneSetCCResult)
|
|
|
|
return VTBits;
|
|
|
|
break;
|
2006-05-06 23:40:29 +00:00
|
|
|
case ISD::ROTL:
|
|
|
|
case ISD::ROTR:
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
|
|
unsigned RotAmt = C->getValue() & (VTBits-1);
|
|
|
|
|
|
|
|
// Handle rotate right by N like a rotate left by 32-N.
|
|
|
|
if (Op.getOpcode() == ISD::ROTR)
|
|
|
|
RotAmt = (VTBits-RotAmt) & (VTBits-1);
|
|
|
|
|
|
|
|
// If we aren't rotating out all of the known-in sign bits, return the
|
|
|
|
// number that are left. This handles rotl(sext(x), 1) for example.
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (Tmp > RotAmt+1) return Tmp-RotAmt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::ADD:
|
|
|
|
// Add can have at most one carry bit. Thus we know that the output
|
|
|
|
// is, at worst, one more bit than the inputs.
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (Tmp == 1) return 1; // Early out.
|
|
|
|
|
|
|
|
// Special case decrementing a value (ADD X, -1):
|
|
|
|
if (ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(Op.getOperand(0)))
|
|
|
|
if (CRHS->isAllOnesValue()) {
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
uint64_t Mask = MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
|
|
|
|
// If the input is known to be 0 or 1, the output is 0/-1, which is all
|
|
|
|
// sign bits set.
|
|
|
|
if ((KnownZero|1) == Mask)
|
|
|
|
return VTBits;
|
|
|
|
|
|
|
|
// If we are subtracting one from a positive number, there is no carry
|
|
|
|
// out of the result.
|
|
|
|
if (KnownZero & MVT::getIntVTSignBit(VT))
|
|
|
|
return Tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1);
|
|
|
|
if (Tmp2 == 1) return 1;
|
|
|
|
return std::min(Tmp, Tmp2)-1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ISD::SUB:
|
|
|
|
Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1);
|
|
|
|
if (Tmp2 == 1) return 1;
|
|
|
|
|
|
|
|
// Handle NEG.
|
|
|
|
if (ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(Op.getOperand(0)))
|
|
|
|
if (CLHS->getValue() == 0) {
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
uint64_t Mask = MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
// If the input is known to be 0 or 1, the output is 0/-1, which is all
|
|
|
|
// sign bits set.
|
|
|
|
if ((KnownZero|1) == Mask)
|
|
|
|
return VTBits;
|
|
|
|
|
|
|
|
// If the input is known to be positive (the sign bit is known clear),
|
|
|
|
// the output of the NEG has the same number of sign bits as the input.
|
|
|
|
if (KnownZero & MVT::getIntVTSignBit(VT))
|
|
|
|
return Tmp2;
|
|
|
|
|
|
|
|
// Otherwise, we treat this like a SUB.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub can have at most one carry bit. Thus we know that the output
|
|
|
|
// is, at worst, one more bit than the inputs.
|
|
|
|
Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
|
|
|
|
if (Tmp == 1) return 1; // Early out.
|
|
|
|
return std::min(Tmp, Tmp2)-1;
|
|
|
|
break;
|
|
|
|
case ISD::TRUNCATE:
|
|
|
|
// FIXME: it's tricky to do anything useful for this, but it is an important
|
|
|
|
// case for targets like X86.
|
|
|
|
break;
|
2006-05-06 22:39:59 +00:00
|
|
|
}
|
|
|
|
|
2006-10-04 00:56:09 +00:00
|
|
|
// Handle LOADX separately here. EXTLOAD case will fallthrough.
|
2006-10-09 20:57:25 +00:00
|
|
|
if (Op.getOpcode() == ISD::LOAD) {
|
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
|
|
|
unsigned ExtType = LD->getExtensionType();
|
|
|
|
switch (ExtType) {
|
2006-10-04 00:56:09 +00:00
|
|
|
default: break;
|
|
|
|
case ISD::SEXTLOAD: // '17' bits known
|
2006-10-11 07:10:22 +00:00
|
|
|
Tmp = MVT::getSizeInBits(LD->getLoadedVT());
|
2006-10-04 00:56:09 +00:00
|
|
|
return VTBits-Tmp+1;
|
|
|
|
case ISD::ZEXTLOAD: // '16' bits known
|
2006-10-11 07:10:22 +00:00
|
|
|
Tmp = MVT::getSizeInBits(LD->getLoadedVT());
|
2006-10-04 00:56:09 +00:00
|
|
|
return VTBits-Tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-06 22:39:59 +00:00
|
|
|
// Allow the target to implement this method for its nodes.
|
|
|
|
if (Op.getOpcode() >= ISD::BUILTIN_OP_END ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_VOID) {
|
|
|
|
unsigned NumBits = ComputeNumSignBitsForTargetNode(Op, Depth);
|
|
|
|
if (NumBits > 1) return NumBits;
|
2006-05-06 09:27:13 +00:00
|
|
|
}
|
|
|
|
|
2006-05-06 23:48:13 +00:00
|
|
|
// Finally, if we can prove that the top bits of the result are 0's or 1's,
|
|
|
|
// use this information.
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
uint64_t Mask = MVT::getIntVTBitMask(VT);
|
|
|
|
ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth);
|
|
|
|
|
|
|
|
uint64_t SignBit = MVT::getIntVTSignBit(VT);
|
|
|
|
if (KnownZero & SignBit) { // SignBit is 0
|
|
|
|
Mask = KnownZero;
|
|
|
|
} else if (KnownOne & SignBit) { // SignBit is 1;
|
|
|
|
Mask = KnownOne;
|
|
|
|
} else {
|
|
|
|
// Nothing known.
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, we know that the sign bit in Mask is set. Use CLZ to determine
|
|
|
|
// the number of identical bits in the top of the input value.
|
|
|
|
Mask ^= ~0ULL;
|
|
|
|
Mask <<= 64-VTBits;
|
|
|
|
// Return # leading zeros. We use 'min' here in case Val was zero before
|
|
|
|
// shifting. We don't want to return '64' as for an i32 "0".
|
|
|
|
return std::min(VTBits, CountLeadingZeros_64(Mask));
|
2006-05-06 09:27:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// ComputeNumSignBitsForTargetNode - This method can be implemented by
|
|
|
|
/// targets that want to expose additional information about sign bits to the
|
|
|
|
/// DAG Combiner.
|
|
|
|
unsigned TargetLowering::ComputeNumSignBitsForTargetNode(SDOperand Op,
|
|
|
|
unsigned Depth) const {
|
|
|
|
assert((Op.getOpcode() >= ISD::BUILTIN_OP_END ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
|
|
|
|
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
|
|
|
|
"Should use ComputeNumSignBits if you don't know whether Op"
|
|
|
|
" is a target node!");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-08 22:13:59 +00:00
|
|
|
/// SimplifySetCC - Try to simplify a setcc built with the specified operands
|
|
|
|
/// and cc. If it is unable to simplify it, return a null SDOperand.
|
|
|
|
SDOperand
|
|
|
|
TargetLowering::SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1,
|
|
|
|
ISD::CondCode Cond, bool foldBooleans,
|
|
|
|
DAGCombinerInfo &DCI) const {
|
|
|
|
SelectionDAG &DAG = DCI.DAG;
|
|
|
|
|
|
|
|
// These setcc operations always fold.
|
|
|
|
switch (Cond) {
|
|
|
|
default: break;
|
|
|
|
case ISD::SETFALSE:
|
|
|
|
case ISD::SETFALSE2: return DAG.getConstant(0, VT);
|
|
|
|
case ISD::SETTRUE:
|
|
|
|
case ISD::SETTRUE2: return DAG.getConstant(1, VT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val)) {
|
|
|
|
uint64_t C1 = N1C->getValue();
|
|
|
|
if (isa<ConstantSDNode>(N0.Val)) {
|
|
|
|
return DAG.FoldSetCC(VT, N0, N1, Cond);
|
|
|
|
} else {
|
|
|
|
// If the LHS is '(srl (ctlz x), 5)', the RHS is 0/1, and this is an
|
|
|
|
// equality comparison, then we're just comparing whether X itself is
|
|
|
|
// zero.
|
|
|
|
if (N0.getOpcode() == ISD::SRL && (C1 == 0 || C1 == 1) &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::CTLZ &&
|
|
|
|
N0.getOperand(1).getOpcode() == ISD::Constant) {
|
|
|
|
unsigned ShAmt = cast<ConstantSDNode>(N0.getOperand(1))->getValue();
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
ShAmt == Log2_32(MVT::getSizeInBits(N0.getValueType()))) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
SDOperand Zero = DAG.getConstant(0, N0.getValueType());
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0).getOperand(0),
|
|
|
|
Zero, Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the LHS is a ZERO_EXTEND, perform the comparison on the input.
|
|
|
|
if (N0.getOpcode() == ISD::ZERO_EXTEND) {
|
|
|
|
unsigned InSize = MVT::getSizeInBits(N0.getOperand(0).getValueType());
|
|
|
|
|
|
|
|
// If the comparison constant has bits in the upper part, the
|
|
|
|
// zero-extended value could never match.
|
|
|
|
if (C1 & (~0ULL << InSize)) {
|
|
|
|
unsigned VSize = MVT::getSizeInBits(N0.getValueType());
|
|
|
|
switch (Cond) {
|
|
|
|
case ISD::SETUGT:
|
|
|
|
case ISD::SETUGE:
|
|
|
|
case ISD::SETEQ: return DAG.getConstant(0, VT);
|
|
|
|
case ISD::SETULT:
|
|
|
|
case ISD::SETULE:
|
|
|
|
case ISD::SETNE: return DAG.getConstant(1, VT);
|
|
|
|
case ISD::SETGT:
|
|
|
|
case ISD::SETGE:
|
|
|
|
// True if the sign bit of C1 is set.
|
2007-02-24 02:09:29 +00:00
|
|
|
return DAG.getConstant((C1 & (1ULL << (VSize-1))) != 0, VT);
|
2007-02-08 22:13:59 +00:00
|
|
|
case ISD::SETLT:
|
|
|
|
case ISD::SETLE:
|
|
|
|
// True if the sign bit of C1 isn't set.
|
2007-02-24 02:09:29 +00:00
|
|
|
return DAG.getConstant((C1 & (1ULL << (VSize-1))) == 0, VT);
|
2007-02-08 22:13:59 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we can perform the comparison with the low bits.
|
|
|
|
switch (Cond) {
|
|
|
|
case ISD::SETEQ:
|
|
|
|
case ISD::SETNE:
|
|
|
|
case ISD::SETUGT:
|
|
|
|
case ISD::SETUGE:
|
|
|
|
case ISD::SETULT:
|
|
|
|
case ISD::SETULE:
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(C1, N0.getOperand(0).getValueType()),
|
|
|
|
Cond);
|
|
|
|
default:
|
|
|
|
break; // todo, be more careful with signed comparisons
|
|
|
|
}
|
|
|
|
} else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
|
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
|
|
|
MVT::ValueType ExtSrcTy = cast<VTSDNode>(N0.getOperand(1))->getVT();
|
|
|
|
unsigned ExtSrcTyBits = MVT::getSizeInBits(ExtSrcTy);
|
|
|
|
MVT::ValueType ExtDstTy = N0.getValueType();
|
|
|
|
unsigned ExtDstTyBits = MVT::getSizeInBits(ExtDstTy);
|
|
|
|
|
|
|
|
// If the extended part has any inconsistent bits, it cannot ever
|
|
|
|
// compare equal. In other words, they have to be all ones or all
|
|
|
|
// zeros.
|
|
|
|
uint64_t ExtBits =
|
|
|
|
(~0ULL >> (64-ExtSrcTyBits)) & (~0ULL << (ExtDstTyBits-1));
|
|
|
|
if ((C1 & ExtBits) != 0 && (C1 & ExtBits) != ExtBits)
|
|
|
|
return DAG.getConstant(Cond == ISD::SETNE, VT);
|
|
|
|
|
|
|
|
SDOperand ZextOp;
|
|
|
|
MVT::ValueType Op0Ty = N0.getOperand(0).getValueType();
|
|
|
|
if (Op0Ty == ExtSrcTy) {
|
|
|
|
ZextOp = N0.getOperand(0);
|
|
|
|
} else {
|
|
|
|
int64_t Imm = ~0ULL >> (64-ExtSrcTyBits);
|
|
|
|
ZextOp = DAG.getNode(ISD::AND, Op0Ty, N0.getOperand(0),
|
|
|
|
DAG.getConstant(Imm, Op0Ty));
|
|
|
|
}
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(ZextOp.Val);
|
|
|
|
// Otherwise, make this a use of a zext.
|
|
|
|
return DAG.getSetCC(VT, ZextOp,
|
|
|
|
DAG.getConstant(C1 & (~0ULL>>(64-ExtSrcTyBits)),
|
|
|
|
ExtDstTy),
|
|
|
|
Cond);
|
|
|
|
} else if ((N1C->getValue() == 0 || N1C->getValue() == 1) &&
|
|
|
|
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
|
|
|
|
|
|
|
|
// SETCC (SETCC), [0|1], [EQ|NE] -> SETCC
|
|
|
|
if (N0.getOpcode() == ISD::SETCC) {
|
|
|
|
bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getValue() != 1);
|
|
|
|
if (TrueWhenTrue)
|
|
|
|
return N0;
|
|
|
|
|
|
|
|
// Invert the condition.
|
|
|
|
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
|
|
|
|
CC = ISD::getSetCCInverse(CC,
|
|
|
|
MVT::isInteger(N0.getOperand(0).getValueType()));
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N0.getOperand(1), CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((N0.getOpcode() == ISD::XOR ||
|
|
|
|
(N0.getOpcode() == ISD::AND &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR &&
|
|
|
|
N0.getOperand(1) == N0.getOperand(0).getOperand(1))) &&
|
|
|
|
isa<ConstantSDNode>(N0.getOperand(1)) &&
|
|
|
|
cast<ConstantSDNode>(N0.getOperand(1))->getValue() == 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.
|
|
|
|
if (MaskedValueIsZero(N0, MVT::getIntVTBitMask(N0.getValueType())-1)){
|
|
|
|
// Okay, get the un-inverted input value.
|
|
|
|
SDOperand Val;
|
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
Val = N0.getOperand(0);
|
|
|
|
else {
|
|
|
|
assert(N0.getOpcode() == ISD::AND &&
|
|
|
|
N0.getOperand(0).getOpcode() == ISD::XOR);
|
|
|
|
// ((X^1)&1)^1 -> X & 1
|
|
|
|
Val = DAG.getNode(ISD::AND, N0.getValueType(),
|
|
|
|
N0.getOperand(0).getOperand(0),
|
|
|
|
N0.getOperand(1));
|
|
|
|
}
|
|
|
|
return DAG.getSetCC(VT, Val, N1,
|
|
|
|
Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t MinVal, MaxVal;
|
|
|
|
unsigned OperandBitSize = MVT::getSizeInBits(N1C->getValueType(0));
|
|
|
|
if (ISD::isSignedIntSetCC(Cond)) {
|
|
|
|
MinVal = 1ULL << (OperandBitSize-1);
|
|
|
|
if (OperandBitSize != 1) // Avoid X >> 64, which is undefined.
|
|
|
|
MaxVal = ~0ULL >> (65-OperandBitSize);
|
|
|
|
else
|
|
|
|
MaxVal = 0;
|
|
|
|
} else {
|
|
|
|
MinVal = 0;
|
|
|
|
MaxVal = ~0ULL >> (64-OperandBitSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
--C1; // X >= C0 --> X > (C0-1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(C1, N1.getValueType()),
|
|
|
|
(Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Cond == ISD::SETLE || Cond == ISD::SETULE) {
|
|
|
|
if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true
|
|
|
|
++C1; // X <= C0 --> X < (C0+1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(C1, 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(VT, N0, N1, ISD::SETNE);
|
|
|
|
// Canonicalize setlt X, Max --> setne X, Max
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MaxVal)
|
|
|
|
return DAG.getSetCC(VT, N0, N1, ISD::SETNE);
|
|
|
|
|
|
|
|
// If we have setult X, 1, turn it into seteq X, 0
|
|
|
|
if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal+1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(MinVal, N0.getValueType()),
|
|
|
|
ISD::SETEQ);
|
|
|
|
// If we have setugt X, Max-1, turn it into seteq X, Max
|
|
|
|
else if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1)
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(MaxVal, N0.getValueType()),
|
|
|
|
ISD::SETEQ);
|
|
|
|
|
|
|
|
// If we have "setcc X, C0", check to see if we can shrink the immediate
|
|
|
|
// by changing cc.
|
|
|
|
|
|
|
|
// SETUGT X, SINTMAX -> SETLT X, 0
|
|
|
|
if (Cond == ISD::SETUGT && OperandBitSize != 1 &&
|
|
|
|
C1 == (~0ULL >> (65-OperandBitSize)))
|
|
|
|
return DAG.getSetCC(VT, N0, DAG.getConstant(0, N1.getValueType()),
|
|
|
|
ISD::SETLT);
|
|
|
|
|
|
|
|
// FIXME: Implement the rest of these.
|
|
|
|
|
|
|
|
// Fold bit comparisons when we can.
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
VT == N0.getValueType() && N0.getOpcode() == ISD::AND)
|
|
|
|
if (ConstantSDNode *AndRHS =
|
|
|
|
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if the AND RHS is a single bit.
|
|
|
|
if (isPowerOf2_64(AndRHS->getValue())) {
|
|
|
|
return DAG.getNode(ISD::SRL, VT, N0,
|
|
|
|
DAG.getConstant(Log2_64(AndRHS->getValue()),
|
|
|
|
getShiftAmountTy()));
|
|
|
|
}
|
|
|
|
} else if (Cond == ISD::SETEQ && C1 == AndRHS->getValue()) {
|
|
|
|
// (X & 8) == 8 --> (X & 8) >> 3
|
|
|
|
// Perform the xform if C1 is a single bit.
|
|
|
|
if (isPowerOf2_64(C1)) {
|
|
|
|
return DAG.getNode(ISD::SRL, VT, N0,
|
|
|
|
DAG.getConstant(Log2_64(C1), getShiftAmountTy()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (isa<ConstantSDNode>(N0.Val)) {
|
|
|
|
// Ensure that the constant occurs on the RHS.
|
|
|
|
return DAG.getSetCC(VT, N1, N0, ISD::getSetCCSwappedOperands(Cond));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isa<ConstantFPSDNode>(N0.Val)) {
|
|
|
|
// Constant fold or commute setcc.
|
|
|
|
SDOperand O = DAG.FoldSetCC(VT, N0, N1, Cond);
|
|
|
|
if (O.Val) return O;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N0 == N1) {
|
|
|
|
// We can always fold X == X for integer setcc's.
|
|
|
|
if (MVT::isInteger(N0.getValueType()))
|
|
|
|
return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT);
|
|
|
|
unsigned UOF = ISD::getUnorderedFlavor(Cond);
|
|
|
|
if (UOF == 2) // FP operators that are undefined on NaNs.
|
|
|
|
return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT);
|
|
|
|
if (UOF == unsigned(ISD::isTrueWhenEqual(Cond)))
|
|
|
|
return DAG.getConstant(UOF, VT);
|
|
|
|
// Otherwise, we can't fold it. However, we can simplify it to SETUO/SETO
|
|
|
|
// if it is not already.
|
|
|
|
ISD::CondCode NewCond = UOF == 0 ? ISD::SETO : ISD::SETUO;
|
|
|
|
if (NewCond != Cond)
|
|
|
|
return DAG.getSetCC(VT, N0, N1, NewCond);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
|
|
|
|
MVT::isInteger(N0.getValueType())) {
|
|
|
|
if (N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB ||
|
|
|
|
N0.getOpcode() == ISD::XOR) {
|
|
|
|
// Simplify (X+Y) == (X+Z) --> Y == Z
|
|
|
|
if (N0.getOpcode() == N1.getOpcode()) {
|
|
|
|
if (N0.getOperand(0) == N1.getOperand(0))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(1), Cond);
|
|
|
|
if (N0.getOperand(1) == N1.getOperand(1))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N1.getOperand(0), Cond);
|
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode())) {
|
|
|
|
// If X op Y == Y op X, try other combinations.
|
|
|
|
if (N0.getOperand(0) == N1.getOperand(1))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(0), Cond);
|
|
|
|
if (N0.getOperand(1) == N1.getOperand(0))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), N1.getOperand(1), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(N1)) {
|
|
|
|
if (ConstantSDNode *LHSR = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
|
|
|
// Turn (X+C1) == C2 --> X == C2-C1
|
|
|
|
if (N0.getOpcode() == ISD::ADD && N0.Val->hasOneUse()) {
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(RHSC->getValue()-LHSR->getValue(),
|
|
|
|
N0.getValueType()), Cond);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0.
|
|
|
|
if (N0.getOpcode() == ISD::XOR)
|
|
|
|
// If we know that all of the inverted bits are zero, don't bother
|
|
|
|
// performing the inversion.
|
|
|
|
if (MaskedValueIsZero(N0.getOperand(0), ~LHSR->getValue()))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(LHSR->getValue()^RHSC->getValue(),
|
|
|
|
N0.getValueType()), Cond);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn (C1-X) == C2 --> X == C1-C2
|
|
|
|
if (ConstantSDNode *SUBC = dyn_cast<ConstantSDNode>(N0.getOperand(0))) {
|
|
|
|
if (N0.getOpcode() == ISD::SUB && N0.Val->hasOneUse()) {
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1),
|
|
|
|
DAG.getConstant(SUBC->getValue()-RHSC->getValue(),
|
|
|
|
N0.getValueType()), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simplify (X+Z) == X --> Z == 0
|
|
|
|
if (N0.getOperand(0) == N1)
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(1),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
|
|
|
if (N0.getOperand(1) == N1) {
|
|
|
|
if (DAG.isCommutativeBinOp(N0.getOpcode()))
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0),
|
|
|
|
DAG.getConstant(0, N0.getValueType()), Cond);
|
|
|
|
else {
|
|
|
|
assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// (Z-X) == X --> Z == X<<1
|
|
|
|
SDOperand SH = DAG.getNode(ISD::SHL, N1.getValueType(),
|
|
|
|
N1,
|
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(SH.Val);
|
|
|
|
return DAG.getSetCC(VT, N0.getOperand(0), SH, Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB ||
|
|
|
|
N1.getOpcode() == ISD::XOR) {
|
|
|
|
// Simplify X == (X+Z) --> Z == 0
|
|
|
|
if (N1.getOperand(0) == N0) {
|
|
|
|
return DAG.getSetCC(VT, N1.getOperand(1),
|
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
|
|
|
} else if (N1.getOperand(1) == N0) {
|
|
|
|
if (DAG.isCommutativeBinOp(N1.getOpcode())) {
|
|
|
|
return DAG.getSetCC(VT, N1.getOperand(0),
|
|
|
|
DAG.getConstant(0, N1.getValueType()), Cond);
|
|
|
|
} else {
|
|
|
|
assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!");
|
|
|
|
// X == (Z-X) --> X<<1 == Z
|
|
|
|
SDOperand SH = DAG.getNode(ISD::SHL, N1.getValueType(), N0,
|
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(SH.Val);
|
|
|
|
return DAG.getSetCC(VT, SH, N1.getOperand(0), Cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fold away ALL boolean setcc's.
|
|
|
|
SDOperand Temp;
|
|
|
|
if (N0.getValueType() == MVT::i1 && foldBooleans) {
|
|
|
|
switch (Cond) {
|
|
|
|
default: assert(0 && "Unknown integer setcc!");
|
|
|
|
case ISD::SETEQ: // X == Y -> (X^Y)^1
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, N1);
|
|
|
|
N0 = DAG.getNode(ISD::XOR, MVT::i1, Temp, DAG.getConstant(1, MVT::i1));
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(Temp.Val);
|
|
|
|
break;
|
|
|
|
case ISD::SETNE: // X != Y --> (X^Y)
|
|
|
|
N0 = DAG.getNode(ISD::XOR, MVT::i1, N0, N1);
|
|
|
|
break;
|
|
|
|
case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> X^1 & Y
|
|
|
|
case ISD::SETULT: // X <u Y --> X == 0 & Y == 1 --> X^1 & Y
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::AND, MVT::i1, N1, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(Temp.Val);
|
|
|
|
break;
|
|
|
|
case ISD::SETLT: // X <s Y --> X == 1 & Y == 0 --> Y^1 & X
|
|
|
|
case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> Y^1 & X
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::AND, MVT::i1, N0, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(Temp.Val);
|
|
|
|
break;
|
|
|
|
case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> X^1 | Y
|
|
|
|
case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> X^1 | Y
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::OR, MVT::i1, N1, Temp);
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(Temp.Val);
|
|
|
|
break;
|
|
|
|
case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> Y^1 | X
|
|
|
|
case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> Y^1 | X
|
|
|
|
Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1));
|
|
|
|
N0 = DAG.getNode(ISD::OR, MVT::i1, N0, Temp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (VT != MVT::i1) {
|
|
|
|
if (!DCI.isCalledByLegalizer())
|
|
|
|
DCI.AddToWorklist(N0.Val);
|
|
|
|
// FIXME: If running after legalize, we probably can't do this.
|
|
|
|
N0 = DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
|
|
|
|
}
|
|
|
|
return N0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Could not fold it.
|
|
|
|
return SDOperand();
|
|
|
|
}
|
|
|
|
|
2006-03-01 04:52:55 +00:00
|
|
|
SDOperand TargetLowering::
|
|
|
|
PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
|
|
|
// Default implementation: no optimization.
|
|
|
|
return SDOperand();
|
|
|
|
}
|
|
|
|
|
2006-02-04 02:13:02 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Inline Assembler Implementation Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TargetLowering::ConstraintType
|
2007-03-25 02:14:49 +00:00
|
|
|
TargetLowering::getConstraintType(const std::string &Constraint) const {
|
2006-02-04 02:13:02 +00:00
|
|
|
// FIXME: lots more standard ones to handle.
|
2007-03-25 02:14:49 +00:00
|
|
|
if (Constraint.size() == 1) {
|
|
|
|
switch (Constraint[0]) {
|
|
|
|
default: break;
|
|
|
|
case 'r': return C_RegisterClass;
|
|
|
|
case 'm': // memory
|
|
|
|
case 'o': // offsetable
|
|
|
|
case 'V': // not offsetable
|
|
|
|
return C_Memory;
|
|
|
|
case 'i': // Simple Integer or Relocatable Constant
|
|
|
|
case 'n': // Simple Integer
|
|
|
|
case 's': // Relocatable Constant
|
2007-03-25 04:35:41 +00:00
|
|
|
case 'X': // Allow ANY value.
|
2007-03-25 02:14:49 +00:00
|
|
|
case 'I': // Target registers.
|
|
|
|
case 'J':
|
|
|
|
case 'K':
|
|
|
|
case 'L':
|
|
|
|
case 'M':
|
|
|
|
case 'N':
|
|
|
|
case 'O':
|
|
|
|
case 'P':
|
|
|
|
return C_Other;
|
|
|
|
}
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
2007-03-25 02:18:14 +00:00
|
|
|
|
|
|
|
if (Constraint.size() > 1 && Constraint[0] == '{' &&
|
|
|
|
Constraint[Constraint.size()-1] == '}')
|
|
|
|
return C_Register;
|
2007-03-25 02:14:49 +00:00
|
|
|
return C_Unknown;
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
|
|
|
|
2006-10-31 19:40:43 +00:00
|
|
|
/// isOperandValidForConstraint - Return the specified operand (possibly
|
|
|
|
/// modified) if the specified SDOperand is valid for the specified target
|
|
|
|
/// constraint letter, otherwise return null.
|
|
|
|
SDOperand TargetLowering::isOperandValidForConstraint(SDOperand Op,
|
|
|
|
char ConstraintLetter,
|
|
|
|
SelectionDAG &DAG) {
|
2006-02-04 02:13:02 +00:00
|
|
|
switch (ConstraintLetter) {
|
2007-02-17 06:00:35 +00:00
|
|
|
default: break;
|
2006-02-04 02:13:02 +00:00
|
|
|
case 'i': // Simple Integer or Relocatable Constant
|
|
|
|
case 'n': // Simple Integer
|
|
|
|
case 's': // Relocatable Constant
|
2007-03-25 04:35:41 +00:00
|
|
|
case 'X': // Allows any operand.
|
2007-02-17 06:00:35 +00:00
|
|
|
// These are okay if the operand is either a global variable address or a
|
|
|
|
// simple immediate value. If we have one of these, map to the TargetXXX
|
|
|
|
// version so that the value itself doesn't get selected.
|
|
|
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
|
|
|
|
// Simple constants are not allowed for 's'.
|
|
|
|
if (ConstraintLetter != 's')
|
|
|
|
return DAG.getTargetConstant(C->getValue(), Op.getValueType());
|
|
|
|
}
|
|
|
|
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) {
|
|
|
|
if (ConstraintLetter != 'n')
|
|
|
|
return DAG.getTargetGlobalAddress(GA->getGlobal(), Op.getValueType(),
|
|
|
|
GA->getOffset());
|
|
|
|
}
|
|
|
|
break;
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
2007-02-17 06:00:35 +00:00
|
|
|
return SDOperand(0,0);
|
2006-02-04 02:13:02 +00:00
|
|
|
}
|
|
|
|
|
2006-01-26 20:37:03 +00:00
|
|
|
std::vector<unsigned> TargetLowering::
|
2006-02-22 00:56:39 +00:00
|
|
|
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
|
|
|
MVT::ValueType VT) const {
|
|
|
|
return std::vector<unsigned>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
|
2006-02-21 23:11:00 +00:00
|
|
|
getRegForInlineAsmConstraint(const std::string &Constraint,
|
|
|
|
MVT::ValueType VT) const {
|
2006-02-22 00:56:39 +00:00
|
|
|
if (Constraint[0] != '{')
|
|
|
|
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
2006-02-01 01:29:47 +00:00
|
|
|
assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
|
|
|
|
|
|
|
|
// Remove the braces from around the name.
|
|
|
|
std::string RegName(Constraint.begin()+1, Constraint.end()-1);
|
2006-02-22 00:56:39 +00:00
|
|
|
|
|
|
|
// Figure out which register class contains this reg.
|
2006-01-26 20:37:03 +00:00
|
|
|
const MRegisterInfo *RI = TM.getRegisterInfo();
|
2006-02-22 00:56:39 +00:00
|
|
|
for (MRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
|
|
|
|
E = RI->regclass_end(); RCI != E; ++RCI) {
|
|
|
|
const TargetRegisterClass *RC = *RCI;
|
2006-02-22 23:00:51 +00:00
|
|
|
|
|
|
|
// If none of the the value types for this register class are valid, we
|
|
|
|
// can't use it. For example, 64-bit reg classes on 32-bit targets.
|
|
|
|
bool isLegal = false;
|
|
|
|
for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (isTypeLegal(*I)) {
|
|
|
|
isLegal = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLegal) continue;
|
|
|
|
|
2006-02-22 00:56:39 +00:00
|
|
|
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
|
|
|
|
I != E; ++I) {
|
2006-02-22 23:00:51 +00:00
|
|
|
if (StringsEqualNoCase(RegName, RI->get(*I).Name))
|
2006-02-22 00:56:39 +00:00
|
|
|
return std::make_pair(*I, RC);
|
|
|
|
}
|
2006-01-26 20:37:03 +00:00
|
|
|
}
|
2006-02-01 01:29:47 +00:00
|
|
|
|
2006-02-22 00:56:39 +00:00
|
|
|
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
2006-01-26 20:37:03 +00:00
|
|
|
}
|
2006-03-13 23:18:16 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loop Strength Reduction hooks
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-03-30 23:14:50 +00:00
|
|
|
/// isLegalAddressingMode - Return true if the addressing mode represented
|
|
|
|
/// by AM is legal for this target, for a load/store of the specified type.
|
|
|
|
bool TargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
|
|
|
const Type *Ty) const {
|
|
|
|
// The default implementation of this implements a conservative RISCy, r+r and
|
|
|
|
// r+i addr mode.
|
|
|
|
|
|
|
|
// Allows a sign-extended 16-bit immediate field.
|
|
|
|
if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No global is ever allowed as a base.
|
|
|
|
if (AM.BaseGV)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only support r+r,
|
|
|
|
switch (AM.Scale) {
|
|
|
|
case 0: // "r+i" or just "i", depending on HasBaseReg.
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed.
|
|
|
|
return false;
|
|
|
|
// Otherwise we have r+r or r+i.
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed.
|
|
|
|
return false;
|
|
|
|
// Allow 2*r as r+r.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-05-16 17:42:15 +00:00
|
|
|
// Magic for divide replacement
|
|
|
|
|
|
|
|
struct ms {
|
|
|
|
int64_t m; // magic number
|
|
|
|
int64_t s; // shift amount
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mu {
|
|
|
|
uint64_t m; // magic number
|
|
|
|
int64_t a; // add indicator
|
|
|
|
int64_t s; // shift amount
|
|
|
|
};
|
|
|
|
|
|
|
|
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
|
|
|
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
|
|
|
/// or -1.
|
|
|
|
static ms magic32(int32_t d) {
|
|
|
|
int32_t p;
|
|
|
|
uint32_t ad, anc, delta, q1, r1, q2, r2, t;
|
|
|
|
const uint32_t two31 = 0x80000000U;
|
|
|
|
struct ms mag;
|
|
|
|
|
|
|
|
ad = abs(d);
|
|
|
|
t = two31 + ((uint32_t)d >> 31);
|
|
|
|
anc = t - 1 - t%ad; // absolute value of nc
|
|
|
|
p = 31; // initialize p
|
|
|
|
q1 = two31/anc; // initialize q1 = 2p/abs(nc)
|
|
|
|
r1 = two31 - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
|
|
|
q2 = two31/ad; // initialize q2 = 2p/abs(d)
|
|
|
|
r2 = two31 - q2*ad; // initialize r2 = rem(2p,abs(d))
|
|
|
|
do {
|
|
|
|
p = p + 1;
|
|
|
|
q1 = 2*q1; // update q1 = 2p/abs(nc)
|
|
|
|
r1 = 2*r1; // update r1 = rem(2p/abs(nc))
|
|
|
|
if (r1 >= anc) { // must be unsigned comparison
|
|
|
|
q1 = q1 + 1;
|
|
|
|
r1 = r1 - anc;
|
|
|
|
}
|
|
|
|
q2 = 2*q2; // update q2 = 2p/abs(d)
|
|
|
|
r2 = 2*r2; // update r2 = rem(2p/abs(d))
|
|
|
|
if (r2 >= ad) { // must be unsigned comparison
|
|
|
|
q2 = q2 + 1;
|
|
|
|
r2 = r2 - ad;
|
|
|
|
}
|
|
|
|
delta = ad - r2;
|
|
|
|
} while (q1 < delta || (q1 == delta && r1 == 0));
|
|
|
|
|
|
|
|
mag.m = (int32_t)(q2 + 1); // make sure to sign extend
|
|
|
|
if (d < 0) mag.m = -mag.m; // resulting magic number
|
|
|
|
mag.s = p - 32; // resulting shift
|
|
|
|
return mag;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// magicu - calculate the magic numbers required to codegen an integer udiv as
|
|
|
|
/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
|
|
|
|
static mu magicu32(uint32_t d) {
|
|
|
|
int32_t p;
|
|
|
|
uint32_t nc, delta, q1, r1, q2, r2;
|
|
|
|
struct mu magu;
|
|
|
|
magu.a = 0; // initialize "add" indicator
|
|
|
|
nc = - 1 - (-d)%d;
|
|
|
|
p = 31; // initialize p
|
|
|
|
q1 = 0x80000000/nc; // initialize q1 = 2p/nc
|
|
|
|
r1 = 0x80000000 - q1*nc; // initialize r1 = rem(2p,nc)
|
|
|
|
q2 = 0x7FFFFFFF/d; // initialize q2 = (2p-1)/d
|
|
|
|
r2 = 0x7FFFFFFF - q2*d; // initialize r2 = rem((2p-1),d)
|
|
|
|
do {
|
|
|
|
p = p + 1;
|
|
|
|
if (r1 >= nc - r1 ) {
|
|
|
|
q1 = 2*q1 + 1; // update q1
|
|
|
|
r1 = 2*r1 - nc; // update r1
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
q1 = 2*q1; // update q1
|
|
|
|
r1 = 2*r1; // update r1
|
|
|
|
}
|
|
|
|
if (r2 + 1 >= d - r2) {
|
|
|
|
if (q2 >= 0x7FFFFFFF) magu.a = 1;
|
|
|
|
q2 = 2*q2 + 1; // update q2
|
|
|
|
r2 = 2*r2 + 1 - d; // update r2
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (q2 >= 0x80000000) magu.a = 1;
|
|
|
|
q2 = 2*q2; // update q2
|
|
|
|
r2 = 2*r2 + 1; // update r2
|
|
|
|
}
|
|
|
|
delta = d - 1 - r2;
|
|
|
|
} while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0)));
|
|
|
|
magu.m = q2 + 1; // resulting magic number
|
|
|
|
magu.s = p - 32; // resulting shift
|
|
|
|
return magu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
|
|
|
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
|
|
|
/// or -1.
|
|
|
|
static ms magic64(int64_t d) {
|
|
|
|
int64_t p;
|
|
|
|
uint64_t ad, anc, delta, q1, r1, q2, r2, t;
|
|
|
|
const uint64_t two63 = 9223372036854775808ULL; // 2^63
|
|
|
|
struct ms mag;
|
|
|
|
|
|
|
|
ad = d >= 0 ? d : -d;
|
|
|
|
t = two63 + ((uint64_t)d >> 63);
|
|
|
|
anc = t - 1 - t%ad; // absolute value of nc
|
|
|
|
p = 63; // initialize p
|
|
|
|
q1 = two63/anc; // initialize q1 = 2p/abs(nc)
|
|
|
|
r1 = two63 - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
|
|
|
q2 = two63/ad; // initialize q2 = 2p/abs(d)
|
|
|
|
r2 = two63 - q2*ad; // initialize r2 = rem(2p,abs(d))
|
|
|
|
do {
|
|
|
|
p = p + 1;
|
|
|
|
q1 = 2*q1; // update q1 = 2p/abs(nc)
|
|
|
|
r1 = 2*r1; // update r1 = rem(2p/abs(nc))
|
|
|
|
if (r1 >= anc) { // must be unsigned comparison
|
|
|
|
q1 = q1 + 1;
|
|
|
|
r1 = r1 - anc;
|
|
|
|
}
|
|
|
|
q2 = 2*q2; // update q2 = 2p/abs(d)
|
|
|
|
r2 = 2*r2; // update r2 = rem(2p/abs(d))
|
|
|
|
if (r2 >= ad) { // must be unsigned comparison
|
|
|
|
q2 = q2 + 1;
|
|
|
|
r2 = r2 - ad;
|
|
|
|
}
|
|
|
|
delta = ad - r2;
|
|
|
|
} while (q1 < delta || (q1 == delta && r1 == 0));
|
|
|
|
|
|
|
|
mag.m = q2 + 1;
|
|
|
|
if (d < 0) mag.m = -mag.m; // resulting magic number
|
|
|
|
mag.s = p - 64; // resulting shift
|
|
|
|
return mag;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// magicu - calculate the magic numbers required to codegen an integer udiv as
|
|
|
|
/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
|
|
|
|
static mu magicu64(uint64_t d)
|
|
|
|
{
|
|
|
|
int64_t p;
|
|
|
|
uint64_t nc, delta, q1, r1, q2, r2;
|
|
|
|
struct mu magu;
|
|
|
|
magu.a = 0; // initialize "add" indicator
|
|
|
|
nc = - 1 - (-d)%d;
|
|
|
|
p = 63; // initialize p
|
|
|
|
q1 = 0x8000000000000000ull/nc; // initialize q1 = 2p/nc
|
|
|
|
r1 = 0x8000000000000000ull - q1*nc; // initialize r1 = rem(2p,nc)
|
|
|
|
q2 = 0x7FFFFFFFFFFFFFFFull/d; // initialize q2 = (2p-1)/d
|
|
|
|
r2 = 0x7FFFFFFFFFFFFFFFull - q2*d; // initialize r2 = rem((2p-1),d)
|
|
|
|
do {
|
|
|
|
p = p + 1;
|
|
|
|
if (r1 >= nc - r1 ) {
|
|
|
|
q1 = 2*q1 + 1; // update q1
|
|
|
|
r1 = 2*r1 - nc; // update r1
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
q1 = 2*q1; // update q1
|
|
|
|
r1 = 2*r1; // update r1
|
|
|
|
}
|
|
|
|
if (r2 + 1 >= d - r2) {
|
|
|
|
if (q2 >= 0x7FFFFFFFFFFFFFFFull) magu.a = 1;
|
|
|
|
q2 = 2*q2 + 1; // update q2
|
|
|
|
r2 = 2*r2 + 1 - d; // update r2
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (q2 >= 0x8000000000000000ull) magu.a = 1;
|
|
|
|
q2 = 2*q2; // update q2
|
|
|
|
r2 = 2*r2 + 1; // update r2
|
|
|
|
}
|
|
|
|
delta = d - 1 - r2;
|
2006-05-16 17:45:23 +00:00
|
|
|
} while (p < 128 && (q1 < delta || (q1 == delta && r1 == 0)));
|
2006-05-16 17:42:15 +00:00
|
|
|
magu.m = q2 + 1; // resulting magic number
|
|
|
|
magu.s = p - 64; // resulting shift
|
|
|
|
return magu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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>
|
|
|
|
SDOperand TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
|
2007-04-16 18:10:23 +00:00
|
|
|
std::vector<SDNode*>* Created) const {
|
2006-05-16 17:42:15 +00:00
|
|
|
MVT::ValueType VT = N->getValueType(0);
|
|
|
|
|
|
|
|
// Check to see if we can do this.
|
|
|
|
if (!isTypeLegal(VT) || (VT != MVT::i32 && VT != MVT::i64))
|
|
|
|
return SDOperand(); // BuildSDIV only operates on i32 or i64
|
|
|
|
if (!isOperationLegal(ISD::MULHS, VT))
|
|
|
|
return SDOperand(); // Make sure the target supports MULHS.
|
|
|
|
|
|
|
|
int64_t d = cast<ConstantSDNode>(N->getOperand(1))->getSignExtended();
|
|
|
|
ms magics = (VT == MVT::i32) ? magic32(d) : magic64(d);
|
|
|
|
|
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
|
|
|
SDOperand Q = DAG.getNode(ISD::MULHS, VT, N->getOperand(0),
|
|
|
|
DAG.getConstant(magics.m, VT));
|
|
|
|
// If d > 0 and m < 0, add the numerator
|
|
|
|
if (d > 0 && magics.m < 0) {
|
|
|
|
Q = DAG.getNode(ISD::ADD, VT, Q, N->getOperand(0));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(Q.Val);
|
|
|
|
}
|
|
|
|
// If d < 0 and m > 0, subtract the numerator.
|
|
|
|
if (d < 0 && magics.m > 0) {
|
|
|
|
Q = DAG.getNode(ISD::SUB, VT, Q, N->getOperand(0));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(Q.Val);
|
|
|
|
}
|
|
|
|
// Shift right algebraic if shift value is nonzero
|
|
|
|
if (magics.s > 0) {
|
|
|
|
Q = DAG.getNode(ISD::SRA, VT, Q,
|
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy()));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(Q.Val);
|
|
|
|
}
|
|
|
|
// Extract the sign bit and add it to the quotient
|
|
|
|
SDOperand T =
|
|
|
|
DAG.getNode(ISD::SRL, VT, Q, DAG.getConstant(MVT::getSizeInBits(VT)-1,
|
|
|
|
getShiftAmountTy()));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(T.Val);
|
|
|
|
return DAG.getNode(ISD::ADD, VT, Q, T);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant,
|
|
|
|
/// return a DAG expression to select that will generate the same value by
|
|
|
|
/// multiplying by a magic number. See:
|
|
|
|
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
|
|
|
|
SDOperand TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
|
2007-04-16 18:10:23 +00:00
|
|
|
std::vector<SDNode*>* Created) const {
|
2006-05-16 17:42:15 +00:00
|
|
|
MVT::ValueType VT = N->getValueType(0);
|
|
|
|
|
|
|
|
// Check to see if we can do this.
|
|
|
|
if (!isTypeLegal(VT) || (VT != MVT::i32 && VT != MVT::i64))
|
|
|
|
return SDOperand(); // BuildUDIV only operates on i32 or i64
|
|
|
|
if (!isOperationLegal(ISD::MULHU, VT))
|
|
|
|
return SDOperand(); // Make sure the target supports MULHU.
|
|
|
|
|
|
|
|
uint64_t d = cast<ConstantSDNode>(N->getOperand(1))->getValue();
|
|
|
|
mu magics = (VT == MVT::i32) ? magicu32(d) : magicu64(d);
|
|
|
|
|
|
|
|
// Multiply the numerator (operand 0) by the magic value
|
|
|
|
SDOperand Q = DAG.getNode(ISD::MULHU, VT, N->getOperand(0),
|
|
|
|
DAG.getConstant(magics.m, VT));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(Q.Val);
|
|
|
|
|
|
|
|
if (magics.a == 0) {
|
|
|
|
return DAG.getNode(ISD::SRL, VT, Q,
|
|
|
|
DAG.getConstant(magics.s, getShiftAmountTy()));
|
|
|
|
} else {
|
|
|
|
SDOperand NPQ = DAG.getNode(ISD::SUB, VT, N->getOperand(0), Q);
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(NPQ.Val);
|
|
|
|
NPQ = DAG.getNode(ISD::SRL, VT, NPQ,
|
|
|
|
DAG.getConstant(1, getShiftAmountTy()));
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(NPQ.Val);
|
|
|
|
NPQ = DAG.getNode(ISD::ADD, VT, NPQ, Q);
|
|
|
|
if (Created)
|
|
|
|
Created->push_back(NPQ.Val);
|
|
|
|
return DAG.getNode(ISD::SRL, VT, NPQ,
|
|
|
|
DAG.getConstant(magics.s-1, getShiftAmountTy()));
|
|
|
|
}
|
|
|
|
}
|