brintos

brintos / llvm-project-archived public Read only

0
0
Text · 219.9 KiB · 971dfdb Raw
6101 lines · cpp
1//===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This is the parent TargetLowering class for hardware code gen11/// targets.12//13//===----------------------------------------------------------------------===//14 15#include "AMDGPUISelLowering.h"16#include "AMDGPU.h"17#include "AMDGPUInstrInfo.h"18#include "AMDGPUMachineFunction.h"19#include "AMDGPUMemoryUtils.h"20#include "AMDGPUSelectionDAGInfo.h"21#include "SIMachineFunctionInfo.h"22#include "llvm/CodeGen/Analysis.h"23#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"24#include "llvm/CodeGen/MachineFrameInfo.h"25#include "llvm/IR/DiagnosticInfo.h"26#include "llvm/IR/IntrinsicsAMDGPU.h"27#include "llvm/Support/CommandLine.h"28#include "llvm/Support/KnownBits.h"29#include "llvm/Target/TargetMachine.h"30 31using namespace llvm;32 33#include "AMDGPUGenCallingConv.inc"34 35static cl::opt<bool> AMDGPUBypassSlowDiv(36  "amdgpu-bypass-slow-div",37  cl::desc("Skip 64-bit divide for dynamic 32-bit values"),38  cl::init(true));39 40// Find a larger type to do a load / store of a vector with.41EVT AMDGPUTargetLowering::getEquivalentMemType(LLVMContext &Ctx, EVT VT) {42  unsigned StoreSize = VT.getStoreSizeInBits();43  if (StoreSize <= 32)44    return EVT::getIntegerVT(Ctx, StoreSize);45 46  if (StoreSize % 32 == 0)47    return EVT::getVectorVT(Ctx, MVT::i32, StoreSize / 32);48 49  return VT;50}51 52unsigned AMDGPUTargetLowering::numBitsUnsigned(SDValue Op, SelectionDAG &DAG) {53  return DAG.computeKnownBits(Op).countMaxActiveBits();54}55 56unsigned AMDGPUTargetLowering::numBitsSigned(SDValue Op, SelectionDAG &DAG) {57  // In order for this to be a signed 24-bit value, bit 23, must58  // be a sign bit.59  return DAG.ComputeMaxSignificantBits(Op);60}61 62AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM,63                                           const TargetSubtargetInfo &STI,64                                           const AMDGPUSubtarget &AMDGPUSTI)65    : TargetLowering(TM, STI), Subtarget(&AMDGPUSTI) {66  // Always lower memset, memcpy, and memmove intrinsics to load/store67  // instructions, rather then generating calls to memset, mempcy or memmove.68  MaxStoresPerMemset = MaxStoresPerMemsetOptSize = ~0U;69  MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = ~0U;70  MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = ~0U;71 72  // Enable ganging up loads and stores in the memcpy DAG lowering.73  MaxGluedStoresPerMemcpy = 16;74 75  // Lower floating point store/load to integer store/load to reduce the number76  // of patterns in tablegen.77  setOperationAction(ISD::LOAD, MVT::f32, Promote);78  AddPromotedToType(ISD::LOAD, MVT::f32, MVT::i32);79 80  setOperationAction(ISD::LOAD, MVT::v2f32, Promote);81  AddPromotedToType(ISD::LOAD, MVT::v2f32, MVT::v2i32);82 83  setOperationAction(ISD::LOAD, MVT::v3f32, Promote);84  AddPromotedToType(ISD::LOAD, MVT::v3f32, MVT::v3i32);85 86  setOperationAction(ISD::LOAD, MVT::v4f32, Promote);87  AddPromotedToType(ISD::LOAD, MVT::v4f32, MVT::v4i32);88 89  setOperationAction(ISD::LOAD, MVT::v5f32, Promote);90  AddPromotedToType(ISD::LOAD, MVT::v5f32, MVT::v5i32);91 92  setOperationAction(ISD::LOAD, MVT::v6f32, Promote);93  AddPromotedToType(ISD::LOAD, MVT::v6f32, MVT::v6i32);94 95  setOperationAction(ISD::LOAD, MVT::v7f32, Promote);96  AddPromotedToType(ISD::LOAD, MVT::v7f32, MVT::v7i32);97 98  setOperationAction(ISD::LOAD, MVT::v8f32, Promote);99  AddPromotedToType(ISD::LOAD, MVT::v8f32, MVT::v8i32);100 101  setOperationAction(ISD::LOAD, MVT::v9f32, Promote);102  AddPromotedToType(ISD::LOAD, MVT::v9f32, MVT::v9i32);103 104  setOperationAction(ISD::LOAD, MVT::v10f32, Promote);105  AddPromotedToType(ISD::LOAD, MVT::v10f32, MVT::v10i32);106 107  setOperationAction(ISD::LOAD, MVT::v11f32, Promote);108  AddPromotedToType(ISD::LOAD, MVT::v11f32, MVT::v11i32);109 110  setOperationAction(ISD::LOAD, MVT::v12f32, Promote);111  AddPromotedToType(ISD::LOAD, MVT::v12f32, MVT::v12i32);112 113  setOperationAction(ISD::LOAD, MVT::v16f32, Promote);114  AddPromotedToType(ISD::LOAD, MVT::v16f32, MVT::v16i32);115 116  setOperationAction(ISD::LOAD, MVT::v32f32, Promote);117  AddPromotedToType(ISD::LOAD, MVT::v32f32, MVT::v32i32);118 119  setOperationAction(ISD::LOAD, MVT::i64, Promote);120  AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);121 122  setOperationAction(ISD::LOAD, MVT::v2i64, Promote);123  AddPromotedToType(ISD::LOAD, MVT::v2i64, MVT::v4i32);124 125  setOperationAction(ISD::LOAD, MVT::f64, Promote);126  AddPromotedToType(ISD::LOAD, MVT::f64, MVT::v2i32);127 128  setOperationAction(ISD::LOAD, MVT::v2f64, Promote);129  AddPromotedToType(ISD::LOAD, MVT::v2f64, MVT::v4i32);130 131  setOperationAction(ISD::LOAD, MVT::v3i64, Promote);132  AddPromotedToType(ISD::LOAD, MVT::v3i64, MVT::v6i32);133 134  setOperationAction(ISD::LOAD, MVT::v4i64, Promote);135  AddPromotedToType(ISD::LOAD, MVT::v4i64, MVT::v8i32);136 137  setOperationAction(ISD::LOAD, MVT::v3f64, Promote);138  AddPromotedToType(ISD::LOAD, MVT::v3f64, MVT::v6i32);139 140  setOperationAction(ISD::LOAD, MVT::v4f64, Promote);141  AddPromotedToType(ISD::LOAD, MVT::v4f64, MVT::v8i32);142 143  setOperationAction(ISD::LOAD, MVT::v8i64, Promote);144  AddPromotedToType(ISD::LOAD, MVT::v8i64, MVT::v16i32);145 146  setOperationAction(ISD::LOAD, MVT::v8f64, Promote);147  AddPromotedToType(ISD::LOAD, MVT::v8f64, MVT::v16i32);148 149  setOperationAction(ISD::LOAD, MVT::v16i64, Promote);150  AddPromotedToType(ISD::LOAD, MVT::v16i64, MVT::v32i32);151 152  setOperationAction(ISD::LOAD, MVT::v16f64, Promote);153  AddPromotedToType(ISD::LOAD, MVT::v16f64, MVT::v32i32);154 155  setOperationAction(ISD::LOAD, MVT::i128, Promote);156  AddPromotedToType(ISD::LOAD, MVT::i128, MVT::v4i32);157 158  // TODO: Would be better to consume as directly legal159  setOperationAction(ISD::ATOMIC_LOAD, MVT::f32, Promote);160  AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f32, MVT::i32);161 162  setOperationAction(ISD::ATOMIC_LOAD, MVT::f64, Promote);163  AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f64, MVT::i64);164 165  setOperationAction(ISD::ATOMIC_LOAD, MVT::f16, Promote);166  AddPromotedToType(ISD::ATOMIC_LOAD, MVT::f16, MVT::i16);167 168  setOperationAction(ISD::ATOMIC_LOAD, MVT::bf16, Promote);169  AddPromotedToType(ISD::ATOMIC_LOAD, MVT::bf16, MVT::i16);170 171  setOperationAction(ISD::ATOMIC_STORE, MVT::f32, Promote);172  AddPromotedToType(ISD::ATOMIC_STORE, MVT::f32, MVT::i32);173 174  setOperationAction(ISD::ATOMIC_STORE, MVT::f64, Promote);175  AddPromotedToType(ISD::ATOMIC_STORE, MVT::f64, MVT::i64);176 177  setOperationAction(ISD::ATOMIC_STORE, MVT::f16, Promote);178  AddPromotedToType(ISD::ATOMIC_STORE, MVT::f16, MVT::i16);179 180  setOperationAction(ISD::ATOMIC_STORE, MVT::bf16, Promote);181  AddPromotedToType(ISD::ATOMIC_STORE, MVT::bf16, MVT::i16);182 183  // There are no 64-bit extloads. These should be done as a 32-bit extload and184  // an extension to 64-bit.185  for (MVT VT : MVT::integer_valuetypes())186    setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i64, VT,187                     Expand);188 189  for (MVT VT : MVT::integer_valuetypes()) {190    if (VT == MVT::i64)191      continue;192 193    for (auto Op : {ISD::SEXTLOAD, ISD::ZEXTLOAD, ISD::EXTLOAD}) {194      setLoadExtAction(Op, VT, MVT::i1, Promote);195      setLoadExtAction(Op, VT, MVT::i8, Legal);196      setLoadExtAction(Op, VT, MVT::i16, Legal);197      setLoadExtAction(Op, VT, MVT::i32, Expand);198    }199  }200 201  for (MVT VT : MVT::integer_fixedlen_vector_valuetypes())202    for (auto MemVT :203         {MVT::v2i8, MVT::v4i8, MVT::v2i16, MVT::v3i16, MVT::v4i16})204      setLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD, ISD::EXTLOAD}, VT, MemVT,205                       Expand);206 207  setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);208  setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);209  setLoadExtAction(ISD::EXTLOAD, MVT::v2f32, MVT::v2f16, Expand);210  setLoadExtAction(ISD::EXTLOAD, MVT::v2f32, MVT::v2bf16, Expand);211  setLoadExtAction(ISD::EXTLOAD, MVT::v3f32, MVT::v3f16, Expand);212  setLoadExtAction(ISD::EXTLOAD, MVT::v3f32, MVT::v3bf16, Expand);213  setLoadExtAction(ISD::EXTLOAD, MVT::v4f32, MVT::v4f16, Expand);214  setLoadExtAction(ISD::EXTLOAD, MVT::v4f32, MVT::v4bf16, Expand);215  setLoadExtAction(ISD::EXTLOAD, MVT::v8f32, MVT::v8f16, Expand);216  setLoadExtAction(ISD::EXTLOAD, MVT::v8f32, MVT::v8bf16, Expand);217  setLoadExtAction(ISD::EXTLOAD, MVT::v16f32, MVT::v16f16, Expand);218  setLoadExtAction(ISD::EXTLOAD, MVT::v16f32, MVT::v16bf16, Expand);219  setLoadExtAction(ISD::EXTLOAD, MVT::v32f32, MVT::v32f16, Expand);220  setLoadExtAction(ISD::EXTLOAD, MVT::v32f32, MVT::v32bf16, Expand);221 222  setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);223  setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f32, Expand);224  setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3f32, Expand);225  setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f32, Expand);226  setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f32, Expand);227  setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16f32, Expand);228 229  setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);230  setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);231  setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f16, Expand);232  setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2bf16, Expand);233  setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3f16, Expand);234  setLoadExtAction(ISD::EXTLOAD, MVT::v3f64, MVT::v3bf16, Expand);235  setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f16, Expand);236  setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4bf16, Expand);237  setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f16, Expand);238  setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8bf16, Expand);239  setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16f16, Expand);240  setLoadExtAction(ISD::EXTLOAD, MVT::v16f64, MVT::v16bf16, Expand);241 242  setOperationAction(ISD::STORE, MVT::f32, Promote);243  AddPromotedToType(ISD::STORE, MVT::f32, MVT::i32);244 245  setOperationAction(ISD::STORE, MVT::v2f32, Promote);246  AddPromotedToType(ISD::STORE, MVT::v2f32, MVT::v2i32);247 248  setOperationAction(ISD::STORE, MVT::v3f32, Promote);249  AddPromotedToType(ISD::STORE, MVT::v3f32, MVT::v3i32);250 251  setOperationAction(ISD::STORE, MVT::v4f32, Promote);252  AddPromotedToType(ISD::STORE, MVT::v4f32, MVT::v4i32);253 254  setOperationAction(ISD::STORE, MVT::v5f32, Promote);255  AddPromotedToType(ISD::STORE, MVT::v5f32, MVT::v5i32);256 257  setOperationAction(ISD::STORE, MVT::v6f32, Promote);258  AddPromotedToType(ISD::STORE, MVT::v6f32, MVT::v6i32);259 260  setOperationAction(ISD::STORE, MVT::v7f32, Promote);261  AddPromotedToType(ISD::STORE, MVT::v7f32, MVT::v7i32);262 263  setOperationAction(ISD::STORE, MVT::v8f32, Promote);264  AddPromotedToType(ISD::STORE, MVT::v8f32, MVT::v8i32);265 266  setOperationAction(ISD::STORE, MVT::v9f32, Promote);267  AddPromotedToType(ISD::STORE, MVT::v9f32, MVT::v9i32);268 269  setOperationAction(ISD::STORE, MVT::v10f32, Promote);270  AddPromotedToType(ISD::STORE, MVT::v10f32, MVT::v10i32);271 272  setOperationAction(ISD::STORE, MVT::v11f32, Promote);273  AddPromotedToType(ISD::STORE, MVT::v11f32, MVT::v11i32);274 275  setOperationAction(ISD::STORE, MVT::v12f32, Promote);276  AddPromotedToType(ISD::STORE, MVT::v12f32, MVT::v12i32);277 278  setOperationAction(ISD::STORE, MVT::v16f32, Promote);279  AddPromotedToType(ISD::STORE, MVT::v16f32, MVT::v16i32);280 281  setOperationAction(ISD::STORE, MVT::v32f32, Promote);282  AddPromotedToType(ISD::STORE, MVT::v32f32, MVT::v32i32);283 284  setOperationAction(ISD::STORE, MVT::i64, Promote);285  AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);286 287  setOperationAction(ISD::STORE, MVT::v2i64, Promote);288  AddPromotedToType(ISD::STORE, MVT::v2i64, MVT::v4i32);289 290  setOperationAction(ISD::STORE, MVT::f64, Promote);291  AddPromotedToType(ISD::STORE, MVT::f64, MVT::v2i32);292 293  setOperationAction(ISD::STORE, MVT::v2f64, Promote);294  AddPromotedToType(ISD::STORE, MVT::v2f64, MVT::v4i32);295 296  setOperationAction(ISD::STORE, MVT::v3i64, Promote);297  AddPromotedToType(ISD::STORE, MVT::v3i64, MVT::v6i32);298 299  setOperationAction(ISD::STORE, MVT::v3f64, Promote);300  AddPromotedToType(ISD::STORE, MVT::v3f64, MVT::v6i32);301 302  setOperationAction(ISD::STORE, MVT::v4i64, Promote);303  AddPromotedToType(ISD::STORE, MVT::v4i64, MVT::v8i32);304 305  setOperationAction(ISD::STORE, MVT::v4f64, Promote);306  AddPromotedToType(ISD::STORE, MVT::v4f64, MVT::v8i32);307 308  setOperationAction(ISD::STORE, MVT::v8i64, Promote);309  AddPromotedToType(ISD::STORE, MVT::v8i64, MVT::v16i32);310 311  setOperationAction(ISD::STORE, MVT::v8f64, Promote);312  AddPromotedToType(ISD::STORE, MVT::v8f64, MVT::v16i32);313 314  setOperationAction(ISD::STORE, MVT::v16i64, Promote);315  AddPromotedToType(ISD::STORE, MVT::v16i64, MVT::v32i32);316 317  setOperationAction(ISD::STORE, MVT::v16f64, Promote);318  AddPromotedToType(ISD::STORE, MVT::v16f64, MVT::v32i32);319 320  setOperationAction(ISD::STORE, MVT::i128, Promote);321  AddPromotedToType(ISD::STORE, MVT::i128, MVT::v4i32);322 323  setTruncStoreAction(MVT::i64, MVT::i1, Expand);324  setTruncStoreAction(MVT::i64, MVT::i8, Expand);325  setTruncStoreAction(MVT::i64, MVT::i16, Expand);326  setTruncStoreAction(MVT::i64, MVT::i32, Expand);327 328  setTruncStoreAction(MVT::v2i64, MVT::v2i1, Expand);329  setTruncStoreAction(MVT::v2i64, MVT::v2i8, Expand);330  setTruncStoreAction(MVT::v2i64, MVT::v2i16, Expand);331  setTruncStoreAction(MVT::v2i64, MVT::v2i32, Expand);332 333  setTruncStoreAction(MVT::f32, MVT::bf16, Expand);334  setTruncStoreAction(MVT::f32, MVT::f16, Expand);335  setTruncStoreAction(MVT::v2f32, MVT::v2bf16, Expand);336  setTruncStoreAction(MVT::v2f32, MVT::v2f16, Expand);337  setTruncStoreAction(MVT::v3f32, MVT::v3bf16, Expand);338  setTruncStoreAction(MVT::v3f32, MVT::v3f16, Expand);339  setTruncStoreAction(MVT::v4f32, MVT::v4bf16, Expand);340  setTruncStoreAction(MVT::v4f32, MVT::v4f16, Expand);341  setTruncStoreAction(MVT::v8f32, MVT::v8bf16, Expand);342  setTruncStoreAction(MVT::v8f32, MVT::v8f16, Expand);343  setTruncStoreAction(MVT::v16f32, MVT::v16bf16, Expand);344  setTruncStoreAction(MVT::v16f32, MVT::v16f16, Expand);345  setTruncStoreAction(MVT::v32f32, MVT::v32bf16, Expand);346  setTruncStoreAction(MVT::v32f32, MVT::v32f16, Expand);347 348  setTruncStoreAction(MVT::f64, MVT::bf16, Expand);349  setTruncStoreAction(MVT::f64, MVT::f16, Expand);350  setTruncStoreAction(MVT::f64, MVT::f32, Expand);351 352  setTruncStoreAction(MVT::v2f64, MVT::v2f32, Expand);353  setTruncStoreAction(MVT::v2f64, MVT::v2bf16, Expand);354  setTruncStoreAction(MVT::v2f64, MVT::v2f16, Expand);355 356  setTruncStoreAction(MVT::v3i32, MVT::v3i8, Expand);357 358  setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);359  setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);360  setTruncStoreAction(MVT::v3i64, MVT::v3i8, Expand);361  setTruncStoreAction(MVT::v3i64, MVT::v3i1, Expand);362  setTruncStoreAction(MVT::v3f64, MVT::v3f32, Expand);363  setTruncStoreAction(MVT::v3f64, MVT::v3bf16, Expand);364  setTruncStoreAction(MVT::v3f64, MVT::v3f16, Expand);365 366  setTruncStoreAction(MVT::v4i64, MVT::v4i32, Expand);367  setTruncStoreAction(MVT::v4i64, MVT::v4i16, Expand);368  setTruncStoreAction(MVT::v4f64, MVT::v4f32, Expand);369  setTruncStoreAction(MVT::v4f64, MVT::v4bf16, Expand);370  setTruncStoreAction(MVT::v4f64, MVT::v4f16, Expand);371 372  setTruncStoreAction(MVT::v5i32, MVT::v5i1, Expand);373  setTruncStoreAction(MVT::v5i32, MVT::v5i8, Expand);374  setTruncStoreAction(MVT::v5i32, MVT::v5i16, Expand);375 376  setTruncStoreAction(MVT::v6i32, MVT::v6i1, Expand);377  setTruncStoreAction(MVT::v6i32, MVT::v6i8, Expand);378  setTruncStoreAction(MVT::v6i32, MVT::v6i16, Expand);379 380  setTruncStoreAction(MVT::v7i32, MVT::v7i1, Expand);381  setTruncStoreAction(MVT::v7i32, MVT::v7i8, Expand);382  setTruncStoreAction(MVT::v7i32, MVT::v7i16, Expand);383 384  setTruncStoreAction(MVT::v8f64, MVT::v8f32, Expand);385  setTruncStoreAction(MVT::v8f64, MVT::v8bf16, Expand);386  setTruncStoreAction(MVT::v8f64, MVT::v8f16, Expand);387 388  setTruncStoreAction(MVT::v16f64, MVT::v16f32, Expand);389  setTruncStoreAction(MVT::v16f64, MVT::v16bf16, Expand);390  setTruncStoreAction(MVT::v16f64, MVT::v16f16, Expand);391  setTruncStoreAction(MVT::v16i64, MVT::v16i16, Expand);392  setTruncStoreAction(MVT::v16i64, MVT::v16i8, Expand);393  setTruncStoreAction(MVT::v16i64, MVT::v16i8, Expand);394  setTruncStoreAction(MVT::v16i64, MVT::v16i1, Expand);395 396  setOperationAction(ISD::Constant, {MVT::i32, MVT::i64}, Legal);397  setOperationAction(ISD::ConstantFP, {MVT::f32, MVT::f64}, Legal);398 399  setOperationAction({ISD::BR_JT, ISD::BRIND}, MVT::Other, Expand);400 401  // For R600, this is totally unsupported, just custom lower to produce an402  // error.403  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);404 405  // Library functions.  These default to Expand, but we have instructions406  // for them.407  setOperationAction({ISD::FCEIL, ISD::FPOW, ISD::FABS, ISD::FFLOOR,408                      ISD::FROUNDEVEN, ISD::FTRUNC},409                     {MVT::f16, MVT::f32}, Legal);410  setOperationAction({ISD::FMINNUM, ISD::FMAXNUM}, MVT::f32, Legal);411 412  setOperationAction(ISD::FLOG2, MVT::f32, Custom);413  setOperationAction(ISD::FROUND, {MVT::f32, MVT::f64}, Custom);414  setOperationAction({ISD::LROUND, ISD::LLROUND},415                     {MVT::f16, MVT::f32, MVT::f64}, Expand);416 417  setOperationAction(418      {ISD::FLOG, ISD::FLOG10, ISD::FEXP, ISD::FEXP2, ISD::FEXP10}, MVT::f32,419      Custom);420 421  setOperationAction(ISD::FNEARBYINT, {MVT::f16, MVT::f32, MVT::f64}, Custom);422 423  setOperationAction(ISD::FRINT, {MVT::f16, MVT::f32, MVT::f64}, Custom);424 425  setOperationAction({ISD::LRINT, ISD::LLRINT}, {MVT::f16, MVT::f32, MVT::f64},426                     Expand);427 428  setOperationAction(ISD::FREM, {MVT::f16, MVT::f32, MVT::f64}, Expand);429 430  if (Subtarget->has16BitInsts()) {431    setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);432    setOperationAction({ISD::FLOG2, ISD::FEXP2}, MVT::f16, Legal);433  } else {434    setOperationAction(ISD::IS_FPCLASS, {MVT::f32, MVT::f64}, Legal);435    setOperationAction({ISD::FLOG2, ISD::FEXP2}, MVT::f16, Custom);436  }437 438  setOperationAction({ISD::FLOG10, ISD::FLOG, ISD::FEXP, ISD::FEXP10}, MVT::f16,439                     Custom);440 441  setOperationAction(ISD::FCANONICALIZE, {MVT::f32, MVT::f64}, Legal);442  if (Subtarget->has16BitInsts()) {443    setOperationAction(ISD::FCANONICALIZE, MVT::f16, Legal);444  }445 446  // FIXME: These IS_FPCLASS vector fp types are marked custom so it reaches447  // scalarization code. Can be removed when IS_FPCLASS expand isn't called by448  // default unless marked custom/legal.449  setOperationAction(ISD::IS_FPCLASS,450                     {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,451                      MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v16f32,452                      MVT::v2f64, MVT::v3f64, MVT::v4f64, MVT::v8f64,453                      MVT::v16f64},454                     Custom);455 456  if (isTypeLegal(MVT::f16))457    setOperationAction(ISD::IS_FPCLASS,458                       {MVT::v2f16, MVT::v3f16, MVT::v4f16, MVT::v16f16},459                       Custom);460 461  // Expand to fneg + fadd.462  setOperationAction(ISD::FSUB, MVT::f64, Expand);463 464  setOperationAction(ISD::CONCAT_VECTORS,465                     {MVT::v3i32,  MVT::v3f32,  MVT::v4i32,  MVT::v4f32,466                      MVT::v5i32,  MVT::v5f32,  MVT::v6i32,  MVT::v6f32,467                      MVT::v7i32,  MVT::v7f32,  MVT::v8i32,  MVT::v8f32,468                      MVT::v9i32,  MVT::v9f32,  MVT::v10i32, MVT::v10f32,469                      MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},470                     Custom);471 472  setOperationAction(473      ISD::EXTRACT_SUBVECTOR,474      {MVT::v2f32,  MVT::v2i32,  MVT::v3f32,  MVT::v3i32,  MVT::v4f32,475       MVT::v4i32,  MVT::v5f32,  MVT::v5i32,  MVT::v6f32,  MVT::v6i32,476       MVT::v7f32,  MVT::v7i32,  MVT::v8f32,  MVT::v8i32,  MVT::v9f32,477       MVT::v9i32,  MVT::v10i32, MVT::v10f32, MVT::v11i32, MVT::v11f32,478       MVT::v12i32, MVT::v12f32, MVT::v16i32, MVT::v32f32, MVT::v32i32,479       MVT::v2f64,  MVT::v2i64,  MVT::v3f64,  MVT::v3i64,  MVT::v4f64,480       MVT::v4i64,  MVT::v8f64,  MVT::v8i64,  MVT::v16f64, MVT::v16i64},481      Custom);482 483  setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);484  setOperationAction(ISD::FP_TO_FP16, {MVT::f64, MVT::f32}, Custom);485 486  const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };487  for (MVT VT : ScalarIntVTs) {488    // These should use [SU]DIVREM, so set them to expand489    setOperationAction({ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM}, VT,490                       Expand);491 492    // GPU does not have divrem function for signed or unsigned.493    setOperationAction({ISD::SDIVREM, ISD::UDIVREM}, VT, Custom);494 495    // GPU does not have [S|U]MUL_LOHI functions as a single instruction.496    setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, VT, Expand);497 498    setOperationAction({ISD::BSWAP, ISD::CTTZ, ISD::CTLZ}, VT, Expand);499 500    // AMDGPU uses ADDC/SUBC/ADDE/SUBE501    setOperationAction({ISD::ADDC, ISD::SUBC, ISD::ADDE, ISD::SUBE}, VT, Legal);502  }503 504  // The hardware supports 32-bit FSHR, but not FSHL.505  setOperationAction(ISD::FSHR, MVT::i32, Legal);506 507  // The hardware supports 32-bit ROTR, but not ROTL.508  setOperationAction(ISD::ROTL, {MVT::i32, MVT::i64}, Expand);509  setOperationAction(ISD::ROTR, MVT::i64, Expand);510 511  setOperationAction({ISD::MULHU, ISD::MULHS}, MVT::i16, Expand);512 513  setOperationAction({ISD::MUL, ISD::MULHU, ISD::MULHS}, MVT::i64, Expand);514  setOperationAction(515      {ISD::UINT_TO_FP, ISD::SINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT},516      MVT::i64, Custom);517  setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);518 519  setOperationAction({ISD::SMIN, ISD::UMIN, ISD::SMAX, ISD::UMAX}, MVT::i32,520                     Legal);521 522  setOperationAction(523      {ISD::CTTZ, ISD::CTTZ_ZERO_UNDEF, ISD::CTLZ, ISD::CTLZ_ZERO_UNDEF},524      MVT::i64, Custom);525 526  for (auto VT : {MVT::i8, MVT::i16})527    setOperationAction({ISD::CTLZ, ISD::CTLZ_ZERO_UNDEF}, VT, Custom);528 529  static const MVT::SimpleValueType VectorIntTypes[] = {530      MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32, MVT::v6i32, MVT::v7i32,531      MVT::v9i32, MVT::v10i32, MVT::v11i32, MVT::v12i32};532 533  for (MVT VT : VectorIntTypes) {534    // Expand the following operations for the current type by default.535    setOperationAction({ISD::ADD,        ISD::AND,          ISD::FP_TO_SINT,536                        ISD::FP_TO_UINT, ISD::MUL,          ISD::MULHU,537                        ISD::MULHS,      ISD::OR,           ISD::SHL,538                        ISD::SRA,        ISD::SRL,          ISD::ROTL,539                        ISD::ROTR,       ISD::SUB,          ISD::SINT_TO_FP,540                        ISD::UINT_TO_FP, ISD::SDIV,         ISD::UDIV,541                        ISD::SREM,       ISD::UREM,         ISD::SMUL_LOHI,542                        ISD::UMUL_LOHI,  ISD::SDIVREM,      ISD::UDIVREM,543                        ISD::SELECT,     ISD::VSELECT,      ISD::SELECT_CC,544                        ISD::XOR,        ISD::BSWAP,        ISD::CTPOP,545                        ISD::CTTZ,       ISD::CTLZ,         ISD::VECTOR_SHUFFLE,546                        ISD::SETCC,      ISD::ADDRSPACECAST},547                       VT, Expand);548  }549 550  static const MVT::SimpleValueType FloatVectorTypes[] = {551      MVT::v2f32, MVT::v3f32,  MVT::v4f32, MVT::v5f32, MVT::v6f32, MVT::v7f32,552      MVT::v9f32, MVT::v10f32, MVT::v11f32, MVT::v12f32};553 554  for (MVT VT : FloatVectorTypes) {555    setOperationAction(556        {ISD::FABS,          ISD::FMINNUM,        ISD::FMAXNUM,557         ISD::FADD,          ISD::FCEIL,          ISD::FCOS,558         ISD::FDIV,          ISD::FEXP2,          ISD::FEXP,559         ISD::FEXP10,        ISD::FLOG2,          ISD::FREM,560         ISD::FLOG,          ISD::FLOG10,         ISD::FPOW,561         ISD::FFLOOR,        ISD::FTRUNC,         ISD::FMUL,562         ISD::FMA,           ISD::FRINT,          ISD::FNEARBYINT,563         ISD::FSQRT,         ISD::FSIN,           ISD::FSUB,564         ISD::FNEG,          ISD::VSELECT,        ISD::SELECT_CC,565         ISD::FCOPYSIGN,     ISD::VECTOR_SHUFFLE, ISD::SETCC,566         ISD::FCANONICALIZE, ISD::FROUNDEVEN},567        VT, Expand);568  }569 570  // This causes using an unrolled select operation rather than expansion with571  // bit operations. This is in general better, but the alternative using BFI572  // instructions may be better if the select sources are SGPRs.573  setOperationAction(ISD::SELECT, MVT::v2f32, Promote);574  AddPromotedToType(ISD::SELECT, MVT::v2f32, MVT::v2i32);575 576  setOperationAction(ISD::SELECT, MVT::v3f32, Promote);577  AddPromotedToType(ISD::SELECT, MVT::v3f32, MVT::v3i32);578 579  setOperationAction(ISD::SELECT, MVT::v4f32, Promote);580  AddPromotedToType(ISD::SELECT, MVT::v4f32, MVT::v4i32);581 582  setOperationAction(ISD::SELECT, MVT::v5f32, Promote);583  AddPromotedToType(ISD::SELECT, MVT::v5f32, MVT::v5i32);584 585  setOperationAction(ISD::SELECT, MVT::v6f32, Promote);586  AddPromotedToType(ISD::SELECT, MVT::v6f32, MVT::v6i32);587 588  setOperationAction(ISD::SELECT, MVT::v7f32, Promote);589  AddPromotedToType(ISD::SELECT, MVT::v7f32, MVT::v7i32);590 591  setOperationAction(ISD::SELECT, MVT::v9f32, Promote);592  AddPromotedToType(ISD::SELECT, MVT::v9f32, MVT::v9i32);593 594  setOperationAction(ISD::SELECT, MVT::v10f32, Promote);595  AddPromotedToType(ISD::SELECT, MVT::v10f32, MVT::v10i32);596 597  setOperationAction(ISD::SELECT, MVT::v11f32, Promote);598  AddPromotedToType(ISD::SELECT, MVT::v11f32, MVT::v11i32);599 600  setOperationAction(ISD::SELECT, MVT::v12f32, Promote);601  AddPromotedToType(ISD::SELECT, MVT::v12f32, MVT::v12i32);602 603  setSchedulingPreference(Sched::RegPressure);604  setJumpIsExpensive(true);605 606  setMinCmpXchgSizeInBits(32);607  setSupportsUnalignedAtomics(false);608 609  PredictableSelectIsExpensive = false;610 611  // We want to find all load dependencies for long chains of stores to enable612  // merging into very wide vectors. The problem is with vectors with > 4613  // elements. MergeConsecutiveStores will attempt to merge these because x8/x16614  // vectors are a legal type, even though we have to split the loads615  // usually. When we can more precisely specify load legality per address616  // space, we should be able to make FindBetterChain/MergeConsecutiveStores617  // smarter so that they can figure out what to do in 2 iterations without all618  // N > 4 stores on the same chain.619  GatherAllAliasesMaxDepth = 16;620 621  // memcpy/memmove/memset are expanded in the IR, so we shouldn't need to worry622  // about these during lowering.623  MaxStoresPerMemcpy  = 0xffffffff;624  MaxStoresPerMemmove = 0xffffffff;625  MaxStoresPerMemset  = 0xffffffff;626 627  // The expansion for 64-bit division is enormous.628  if (AMDGPUBypassSlowDiv)629    addBypassSlowDiv(64, 32);630 631  setTargetDAGCombine({ISD::BITCAST,    ISD::SHL,632                       ISD::SRA,        ISD::SRL,633                       ISD::TRUNCATE,   ISD::MUL,634                       ISD::SMUL_LOHI,  ISD::UMUL_LOHI,635                       ISD::MULHU,      ISD::MULHS,636                       ISD::SELECT,     ISD::SELECT_CC,637                       ISD::STORE,      ISD::FADD,638                       ISD::FSUB,       ISD::FNEG,639                       ISD::FABS,       ISD::AssertZext,640                       ISD::AssertSext, ISD::INTRINSIC_WO_CHAIN});641 642  setMaxAtomicSizeInBitsSupported(64);643  setMaxDivRemBitWidthSupported(64);644  setMaxLargeFPConvertBitWidthSupported(64);645}646 647bool AMDGPUTargetLowering::mayIgnoreSignedZero(SDValue Op) const {648  if (getTargetMachine().Options.NoSignedZerosFPMath)649    return true;650 651  const auto Flags = Op.getNode()->getFlags();652  if (Flags.hasNoSignedZeros())653    return true;654 655  return false;656}657 658//===----------------------------------------------------------------------===//659// Target Information660//===----------------------------------------------------------------------===//661 662LLVM_READNONE663static bool fnegFoldsIntoOpcode(unsigned Opc) {664  switch (Opc) {665  case ISD::FADD:666  case ISD::FSUB:667  case ISD::FMUL:668  case ISD::FMA:669  case ISD::FMAD:670  case ISD::FMINNUM:671  case ISD::FMAXNUM:672  case ISD::FMINNUM_IEEE:673  case ISD::FMAXNUM_IEEE:674  case ISD::FMINIMUM:675  case ISD::FMAXIMUM:676  case ISD::FMINIMUMNUM:677  case ISD::FMAXIMUMNUM:678  case ISD::SELECT:679  case ISD::FSIN:680  case ISD::FTRUNC:681  case ISD::FRINT:682  case ISD::FNEARBYINT:683  case ISD::FROUNDEVEN:684  case ISD::FCANONICALIZE:685  case AMDGPUISD::RCP:686  case AMDGPUISD::RCP_LEGACY:687  case AMDGPUISD::RCP_IFLAG:688  case AMDGPUISD::SIN_HW:689  case AMDGPUISD::FMUL_LEGACY:690  case AMDGPUISD::FMIN_LEGACY:691  case AMDGPUISD::FMAX_LEGACY:692  case AMDGPUISD::FMED3:693    // TODO: handle llvm.amdgcn.fma.legacy694    return true;695  case ISD::BITCAST:696    llvm_unreachable("bitcast is special cased");697  default:698    return false;699  }700}701 702static bool fnegFoldsIntoOp(const SDNode *N) {703  unsigned Opc = N->getOpcode();704  if (Opc == ISD::BITCAST) {705    // TODO: Is there a benefit to checking the conditions performFNegCombine706    // does? We don't for the other cases.707    SDValue BCSrc = N->getOperand(0);708    if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {709      return BCSrc.getNumOperands() == 2 &&710             BCSrc.getOperand(1).getValueSizeInBits() == 32;711    }712 713    return BCSrc.getOpcode() == ISD::SELECT && BCSrc.getValueType() == MVT::f32;714  }715 716  return fnegFoldsIntoOpcode(Opc);717}718 719/// \p returns true if the operation will definitely need to use a 64-bit720/// encoding, and thus will use a VOP3 encoding regardless of the source721/// modifiers.722LLVM_READONLY723static bool opMustUseVOP3Encoding(const SDNode *N, MVT VT) {724  return (N->getNumOperands() > 2 && N->getOpcode() != ISD::SELECT) ||725         VT == MVT::f64;726}727 728/// Return true if v_cndmask_b32 will support fabs/fneg source modifiers for the729/// type for ISD::SELECT.730LLVM_READONLY731static bool selectSupportsSourceMods(const SDNode *N) {732  // TODO: Only applies if select will be vector733  return N->getValueType(0) == MVT::f32;734}735 736// Most FP instructions support source modifiers, but this could be refined737// slightly.738LLVM_READONLY739static bool hasSourceMods(const SDNode *N) {740  if (isa<MemSDNode>(N))741    return false;742 743  switch (N->getOpcode()) {744  case ISD::CopyToReg:745  case ISD::FDIV:746  case ISD::FREM:747  case ISD::INLINEASM:748  case ISD::INLINEASM_BR:749  case AMDGPUISD::DIV_SCALE:750  case ISD::INTRINSIC_W_CHAIN:751 752  // TODO: Should really be looking at the users of the bitcast. These are753  // problematic because bitcasts are used to legalize all stores to integer754  // types.755  case ISD::BITCAST:756    return false;757  case ISD::INTRINSIC_WO_CHAIN: {758    switch (N->getConstantOperandVal(0)) {759    case Intrinsic::amdgcn_interp_p1:760    case Intrinsic::amdgcn_interp_p2:761    case Intrinsic::amdgcn_interp_mov:762    case Intrinsic::amdgcn_interp_p1_f16:763    case Intrinsic::amdgcn_interp_p2_f16:764      return false;765    default:766      return true;767    }768  }769  case ISD::SELECT:770    return selectSupportsSourceMods(N);771  default:772    return true;773  }774}775 776bool AMDGPUTargetLowering::allUsesHaveSourceMods(const SDNode *N,777                                                 unsigned CostThreshold) {778  // Some users (such as 3-operand FMA/MAD) must use a VOP3 encoding, and thus779  // it is truly free to use a source modifier in all cases. If there are780  // multiple users but for each one will necessitate using VOP3, there will be781  // a code size increase. Try to avoid increasing code size unless we know it782  // will save on the instruction count.783  unsigned NumMayIncreaseSize = 0;784  MVT VT = N->getValueType(0).getScalarType().getSimpleVT();785 786  assert(!N->use_empty());787 788  // XXX - Should this limit number of uses to check?789  for (const SDNode *U : N->users()) {790    if (!hasSourceMods(U))791      return false;792 793    if (!opMustUseVOP3Encoding(U, VT)) {794      if (++NumMayIncreaseSize > CostThreshold)795        return false;796    }797  }798 799  return true;800}801 802EVT AMDGPUTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT,803                                              ISD::NodeType ExtendKind) const {804  assert(!VT.isVector() && "only scalar expected");805 806  // Round to the next multiple of 32-bits.807  unsigned Size = VT.getSizeInBits();808  if (Size <= 32)809    return MVT::i32;810  return EVT::getIntegerVT(Context, 32 * ((Size + 31) / 32));811}812 813unsigned AMDGPUTargetLowering::getVectorIdxWidth(const DataLayout &) const {814  return 32;815}816 817bool AMDGPUTargetLowering::isSelectSupported(SelectSupportKind SelType) const {818  return true;819}820 821// The backend supports 32 and 64 bit floating point immediates.822// FIXME: Why are we reporting vectors of FP immediates as legal?823bool AMDGPUTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,824                                        bool ForCodeSize) const {825  EVT ScalarVT = VT.getScalarType();826  return (ScalarVT == MVT::f32 || ScalarVT == MVT::f64 ||827         (ScalarVT == MVT::f16 && Subtarget->has16BitInsts()));828}829 830// We don't want to shrink f64 / f32 constants.831bool AMDGPUTargetLowering::ShouldShrinkFPConstant(EVT VT) const {832  EVT ScalarVT = VT.getScalarType();833  return (ScalarVT != MVT::f32 && ScalarVT != MVT::f64);834}835 836bool AMDGPUTargetLowering::shouldReduceLoadWidth(837    SDNode *N, ISD::LoadExtType ExtTy, EVT NewVT,838    std::optional<unsigned> ByteOffset) const {839  // TODO: This may be worth removing. Check regression tests for diffs.840  if (!TargetLoweringBase::shouldReduceLoadWidth(N, ExtTy, NewVT, ByteOffset))841    return false;842 843  unsigned NewSize = NewVT.getStoreSizeInBits();844 845  // If we are reducing to a 32-bit load or a smaller multi-dword load,846  // this is always better.847  if (NewSize >= 32)848    return true;849 850  EVT OldVT = N->getValueType(0);851  unsigned OldSize = OldVT.getStoreSizeInBits();852 853  MemSDNode *MN = cast<MemSDNode>(N);854  unsigned AS = MN->getAddressSpace();855  // Do not shrink an aligned scalar load to sub-dword.856  // Scalar engine cannot do sub-dword loads.857  // TODO: Update this for GFX12 which does have scalar sub-dword loads.858  if (OldSize >= 32 && NewSize < 32 && MN->getAlign() >= Align(4) &&859      (AS == AMDGPUAS::CONSTANT_ADDRESS ||860       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT ||861       (isa<LoadSDNode>(N) && AS == AMDGPUAS::GLOBAL_ADDRESS &&862        MN->isInvariant())) &&863      AMDGPU::isUniformMMO(MN->getMemOperand()))864    return false;865 866  // Don't produce extloads from sub 32-bit types. SI doesn't have scalar867  // extloads, so doing one requires using a buffer_load. In cases where we868  // still couldn't use a scalar load, using the wider load shouldn't really869  // hurt anything.870 871  // If the old size already had to be an extload, there's no harm in continuing872  // to reduce the width.873  return (OldSize < 32);874}875 876bool AMDGPUTargetLowering::isLoadBitCastBeneficial(EVT LoadTy, EVT CastTy,877                                                   const SelectionDAG &DAG,878                                                   const MachineMemOperand &MMO) const {879 880  assert(LoadTy.getSizeInBits() == CastTy.getSizeInBits());881 882  if (LoadTy.getScalarType() == MVT::i32)883    return false;884 885  unsigned LScalarSize = LoadTy.getScalarSizeInBits();886  unsigned CastScalarSize = CastTy.getScalarSizeInBits();887 888  if ((LScalarSize >= CastScalarSize) && (CastScalarSize < 32))889    return false;890 891  unsigned Fast = 0;892  return allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(),893                                        CastTy, MMO, &Fast) &&894         Fast;895}896 897// SI+ has instructions for cttz / ctlz for 32-bit values. This is probably also898// profitable with the expansion for 64-bit since it's generally good to899// speculate things.900bool AMDGPUTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {901  return true;902}903 904bool AMDGPUTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {905  return true;906}907 908bool AMDGPUTargetLowering::isSDNodeAlwaysUniform(const SDNode *N) const {909  switch (N->getOpcode()) {910  case ISD::EntryToken:911  case ISD::TokenFactor:912    return true;913  case ISD::INTRINSIC_WO_CHAIN: {914    unsigned IntrID = N->getConstantOperandVal(0);915    return AMDGPU::isIntrinsicAlwaysUniform(IntrID);916  }917  case ISD::INTRINSIC_W_CHAIN: {918    unsigned IntrID = N->getConstantOperandVal(1);919    return AMDGPU::isIntrinsicAlwaysUniform(IntrID);920  }921  case ISD::LOAD:922    if (cast<LoadSDNode>(N)->getMemOperand()->getAddrSpace() ==923        AMDGPUAS::CONSTANT_ADDRESS_32BIT)924      return true;925    return false;926  case AMDGPUISD::SETCC: // ballot-style instruction927    return true;928  }929  return false;930}931 932SDValue AMDGPUTargetLowering::getNegatedExpression(933    SDValue Op, SelectionDAG &DAG, bool LegalOperations, bool ForCodeSize,934    NegatibleCost &Cost, unsigned Depth) const {935 936  switch (Op.getOpcode()) {937  case ISD::FMA:938  case ISD::FMAD: {939    // Negating a fma is not free if it has users without source mods.940    if (!allUsesHaveSourceMods(Op.getNode()))941      return SDValue();942    break;943  }944  case AMDGPUISD::RCP: {945    SDValue Src = Op.getOperand(0);946    EVT VT = Op.getValueType();947    SDLoc SL(Op);948 949    SDValue NegSrc = getNegatedExpression(Src, DAG, LegalOperations,950                                          ForCodeSize, Cost, Depth + 1);951    if (NegSrc)952      return DAG.getNode(AMDGPUISD::RCP, SL, VT, NegSrc, Op->getFlags());953    return SDValue();954  }955  default:956    break;957  }958 959  return TargetLowering::getNegatedExpression(Op, DAG, LegalOperations,960                                              ForCodeSize, Cost, Depth);961}962 963//===---------------------------------------------------------------------===//964// Target Properties965//===---------------------------------------------------------------------===//966 967bool AMDGPUTargetLowering::isFAbsFree(EVT VT) const {968  assert(VT.isFloatingPoint());969 970  // Packed operations do not have a fabs modifier.971  return VT == MVT::f32 || VT == MVT::f64 ||972         (Subtarget->has16BitInsts() && (VT == MVT::f16 || VT == MVT::bf16));973}974 975bool AMDGPUTargetLowering::isFNegFree(EVT VT) const {976  assert(VT.isFloatingPoint());977  // Report this based on the end legalized type.978  VT = VT.getScalarType();979  return VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f16 || VT == MVT::bf16;980}981 982bool AMDGPUTargetLowering:: storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT,983                                                         unsigned NumElem,984                                                         unsigned AS) const {985  return true;986}987 988bool AMDGPUTargetLowering::aggressivelyPreferBuildVectorSources(EVT VecVT) const {989  // There are few operations which truly have vector input operands. Any vector990  // operation is going to involve operations on each component, and a991  // build_vector will be a copy per element, so it always makes sense to use a992  // build_vector input in place of the extracted element to avoid a copy into a993  // super register.994  //995  // We should probably only do this if all users are extracts only, but this996  // should be the common case.997  return true;998}999 1000bool AMDGPUTargetLowering::isTruncateFree(EVT Source, EVT Dest) const {1001  // Truncate is just accessing a subregister.1002 1003  unsigned SrcSize = Source.getSizeInBits();1004  unsigned DestSize = Dest.getSizeInBits();1005 1006  return DestSize < SrcSize && DestSize % 32 == 0 ;1007}1008 1009bool AMDGPUTargetLowering::isTruncateFree(Type *Source, Type *Dest) const {1010  // Truncate is just accessing a subregister.1011 1012  unsigned SrcSize = Source->getScalarSizeInBits();1013  unsigned DestSize = Dest->getScalarSizeInBits();1014 1015  if (DestSize== 16 && Subtarget->has16BitInsts())1016    return SrcSize >= 32;1017 1018  return DestSize < SrcSize && DestSize % 32 == 0;1019}1020 1021bool AMDGPUTargetLowering::isZExtFree(Type *Src, Type *Dest) const {1022  unsigned SrcSize = Src->getScalarSizeInBits();1023  unsigned DestSize = Dest->getScalarSizeInBits();1024 1025  if (SrcSize == 16 && Subtarget->has16BitInsts())1026    return DestSize >= 32;1027 1028  return SrcSize == 32 && DestSize == 64;1029}1030 1031bool AMDGPUTargetLowering::isZExtFree(EVT Src, EVT Dest) const {1032  // Any register load of a 64-bit value really requires 2 32-bit moves. For all1033  // practical purposes, the extra mov 0 to load a 64-bit is free.  As used,1034  // this will enable reducing 64-bit operations the 32-bit, which is always1035  // good.1036 1037  if (Src == MVT::i16)1038    return Dest == MVT::i32 ||Dest == MVT::i64 ;1039 1040  return Src == MVT::i32 && Dest == MVT::i64;1041}1042 1043bool AMDGPUTargetLowering::isNarrowingProfitable(SDNode *N, EVT SrcVT,1044                                                 EVT DestVT) const {1045  switch (N->getOpcode()) {1046  case ISD::ADD:1047  case ISD::SUB:1048  case ISD::SHL:1049  case ISD::SRL:1050  case ISD::SRA:1051  case ISD::AND:1052  case ISD::OR:1053  case ISD::XOR:1054  case ISD::MUL:1055  case ISD::SETCC:1056  case ISD::SELECT:1057  case ISD::SMIN:1058  case ISD::SMAX:1059  case ISD::UMIN:1060  case ISD::UMAX:1061    if (Subtarget->has16BitInsts() &&1062        (!DestVT.isVector() || !Subtarget->hasVOP3PInsts())) {1063      // Don't narrow back down to i16 if promoted to i32 already.1064      if (!N->isDivergent() && DestVT.isInteger() &&1065          DestVT.getScalarSizeInBits() > 1 &&1066          DestVT.getScalarSizeInBits() <= 16 &&1067          SrcVT.getScalarSizeInBits() > 16) {1068        return false;1069      }1070    }1071    return true;1072  default:1073    break;1074  }1075 1076  // There aren't really 64-bit registers, but pairs of 32-bit ones and only a1077  // limited number of native 64-bit operations. Shrinking an operation to fit1078  // in a single 32-bit register should always be helpful. As currently used,1079  // this is much less general than the name suggests, and is only used in1080  // places trying to reduce the sizes of loads. Shrinking loads to < 32-bits is1081  // not profitable, and may actually be harmful.1082  if (isa<LoadSDNode>(N))1083    return SrcVT.getSizeInBits() > 32 && DestVT.getSizeInBits() == 32;1084 1085  return true;1086}1087 1088bool AMDGPUTargetLowering::isDesirableToCommuteWithShift(1089    const SDNode* N, CombineLevel Level) const {1090  assert((N->getOpcode() == ISD::SHL || N->getOpcode() == ISD::SRA ||1091          N->getOpcode() == ISD::SRL) &&1092         "Expected shift op");1093 1094  SDValue ShiftLHS = N->getOperand(0);1095  if (!ShiftLHS->hasOneUse())1096    return false;1097 1098  if (ShiftLHS.getOpcode() == ISD::SIGN_EXTEND &&1099      !ShiftLHS.getOperand(0)->hasOneUse())1100    return false;1101 1102  // Always commute pre-type legalization and right shifts.1103  // We're looking for shl(or(x,y),z) patterns.1104  if (Level < CombineLevel::AfterLegalizeTypes ||1105      N->getOpcode() != ISD::SHL || N->getOperand(0).getOpcode() != ISD::OR)1106    return true;1107 1108  // If only user is a i32 right-shift, then don't destroy a BFE pattern.1109  if (N->getValueType(0) == MVT::i32 && N->hasOneUse() &&1110      (N->user_begin()->getOpcode() == ISD::SRA ||1111       N->user_begin()->getOpcode() == ISD::SRL))1112    return false;1113 1114  // Don't destroy or(shl(load_zext(),c), load_zext()) patterns.1115  auto IsShiftAndLoad = [](SDValue LHS, SDValue RHS) {1116    if (LHS.getOpcode() != ISD::SHL)1117      return false;1118    auto *RHSLd = dyn_cast<LoadSDNode>(RHS);1119    auto *LHS0 = dyn_cast<LoadSDNode>(LHS.getOperand(0));1120    auto *LHS1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));1121    return LHS0 && LHS1 && RHSLd && LHS0->getExtensionType() == ISD::ZEXTLOAD &&1122           LHS1->getAPIntValue() == LHS0->getMemoryVT().getScalarSizeInBits() &&1123           RHSLd->getExtensionType() == ISD::ZEXTLOAD;1124  };1125  SDValue LHS = N->getOperand(0).getOperand(0);1126  SDValue RHS = N->getOperand(0).getOperand(1);1127  return !(IsShiftAndLoad(LHS, RHS) || IsShiftAndLoad(RHS, LHS));1128}1129 1130//===---------------------------------------------------------------------===//1131// TargetLowering Callbacks1132//===---------------------------------------------------------------------===//1133 1134CCAssignFn *AMDGPUCallLowering::CCAssignFnForCall(CallingConv::ID CC,1135                                                  bool IsVarArg) {1136  switch (CC) {1137  case CallingConv::AMDGPU_VS:1138  case CallingConv::AMDGPU_GS:1139  case CallingConv::AMDGPU_PS:1140  case CallingConv::AMDGPU_CS:1141  case CallingConv::AMDGPU_HS:1142  case CallingConv::AMDGPU_ES:1143  case CallingConv::AMDGPU_LS:1144    return CC_AMDGPU;1145  case CallingConv::AMDGPU_CS_Chain:1146  case CallingConv::AMDGPU_CS_ChainPreserve:1147    return CC_AMDGPU_CS_CHAIN;1148  case CallingConv::C:1149  case CallingConv::Fast:1150  case CallingConv::Cold:1151    return CC_AMDGPU_Func;1152  case CallingConv::AMDGPU_Gfx:1153  case CallingConv::AMDGPU_Gfx_WholeWave:1154    return CC_SI_Gfx;1155  case CallingConv::AMDGPU_KERNEL:1156  case CallingConv::SPIR_KERNEL:1157  default:1158    reportFatalUsageError("unsupported calling convention for call");1159  }1160}1161 1162CCAssignFn *AMDGPUCallLowering::CCAssignFnForReturn(CallingConv::ID CC,1163                                                    bool IsVarArg) {1164  switch (CC) {1165  case CallingConv::AMDGPU_KERNEL:1166  case CallingConv::SPIR_KERNEL:1167    llvm_unreachable("kernels should not be handled here");1168  case CallingConv::AMDGPU_VS:1169  case CallingConv::AMDGPU_GS:1170  case CallingConv::AMDGPU_PS:1171  case CallingConv::AMDGPU_CS:1172  case CallingConv::AMDGPU_CS_Chain:1173  case CallingConv::AMDGPU_CS_ChainPreserve:1174  case CallingConv::AMDGPU_HS:1175  case CallingConv::AMDGPU_ES:1176  case CallingConv::AMDGPU_LS:1177    return RetCC_SI_Shader;1178  case CallingConv::AMDGPU_Gfx:1179  case CallingConv::AMDGPU_Gfx_WholeWave:1180    return RetCC_SI_Gfx;1181  case CallingConv::C:1182  case CallingConv::Fast:1183  case CallingConv::Cold:1184    return RetCC_AMDGPU_Func;1185  default:1186    reportFatalUsageError("unsupported calling convention");1187  }1188}1189 1190/// The SelectionDAGBuilder will automatically promote function arguments1191/// with illegal types.  However, this does not work for the AMDGPU targets1192/// since the function arguments are stored in memory as these illegal types.1193/// In order to handle this properly we need to get the original types sizes1194/// from the LLVM IR Function and fixup the ISD:InputArg values before1195/// passing them to AnalyzeFormalArguments()1196 1197/// When the SelectionDAGBuilder computes the Ins, it takes care of splitting1198/// input values across multiple registers.  Each item in the Ins array1199/// represents a single value that will be stored in registers.  Ins[x].VT is1200/// the value type of the value that will be stored in the register, so1201/// whatever SDNode we lower the argument to needs to be this type.1202///1203/// In order to correctly lower the arguments we need to know the size of each1204/// argument.  Since Ins[x].VT gives us the size of the register that will1205/// hold the value, we need to look at Ins[x].ArgVT to see the 'real' type1206/// for the original function argument so that we can deduce the correct memory1207/// type to use for Ins[x].  In most cases the correct memory type will be1208/// Ins[x].ArgVT.  However, this will not always be the case.  If, for example,1209/// we have a kernel argument of type v8i8, this argument will be split into1210/// 8 parts and each part will be represented by its own item in the Ins array.1211/// For each part the Ins[x].ArgVT will be the v8i8, which is the full type of1212/// the argument before it was split.  From this, we deduce that the memory type1213/// for each individual part is i8.  We pass the memory type as LocVT to the1214/// calling convention analysis function and the register type (Ins[x].VT) as1215/// the ValVT.1216void AMDGPUTargetLowering::analyzeFormalArgumentsCompute(1217  CCState &State,1218  const SmallVectorImpl<ISD::InputArg> &Ins) const {1219  const MachineFunction &MF = State.getMachineFunction();1220  const Function &Fn = MF.getFunction();1221  LLVMContext &Ctx = Fn.getContext();1222  const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(MF);1223  const unsigned ExplicitOffset = ST.getExplicitKernelArgOffset();1224  CallingConv::ID CC = Fn.getCallingConv();1225 1226  Align MaxAlign = Align(1);1227  uint64_t ExplicitArgOffset = 0;1228  const DataLayout &DL = Fn.getDataLayout();1229 1230  unsigned InIndex = 0;1231 1232  for (const Argument &Arg : Fn.args()) {1233    const bool IsByRef = Arg.hasByRefAttr();1234    Type *BaseArgTy = Arg.getType();1235    Type *MemArgTy = IsByRef ? Arg.getParamByRefType() : BaseArgTy;1236    Align Alignment = DL.getValueOrABITypeAlignment(1237        IsByRef ? Arg.getParamAlign() : std::nullopt, MemArgTy);1238    MaxAlign = std::max(Alignment, MaxAlign);1239    uint64_t AllocSize = DL.getTypeAllocSize(MemArgTy);1240 1241    uint64_t ArgOffset = alignTo(ExplicitArgOffset, Alignment) + ExplicitOffset;1242    ExplicitArgOffset = alignTo(ExplicitArgOffset, Alignment) + AllocSize;1243 1244    // We're basically throwing away everything passed into us and starting over1245    // to get accurate in-memory offsets. The "PartOffset" is completely useless1246    // to us as computed in Ins.1247    //1248    // We also need to figure out what type legalization is trying to do to get1249    // the correct memory offsets.1250 1251    SmallVector<EVT, 16> ValueVTs;1252    SmallVector<uint64_t, 16> Offsets;1253    ComputeValueVTs(*this, DL, BaseArgTy, ValueVTs, /*MemVTs=*/nullptr,1254                    &Offsets, ArgOffset);1255 1256    for (unsigned Value = 0, NumValues = ValueVTs.size();1257         Value != NumValues; ++Value) {1258      uint64_t BasePartOffset = Offsets[Value];1259 1260      EVT ArgVT = ValueVTs[Value];1261      EVT MemVT = ArgVT;1262      MVT RegisterVT = getRegisterTypeForCallingConv(Ctx, CC, ArgVT);1263      unsigned NumRegs = getNumRegistersForCallingConv(Ctx, CC, ArgVT);1264 1265      if (NumRegs == 1) {1266        // This argument is not split, so the IR type is the memory type.1267        if (ArgVT.isExtended()) {1268          // We have an extended type, like i24, so we should just use the1269          // register type.1270          MemVT = RegisterVT;1271        } else {1272          MemVT = ArgVT;1273        }1274      } else if (ArgVT.isVector() && RegisterVT.isVector() &&1275                 ArgVT.getScalarType() == RegisterVT.getScalarType()) {1276        assert(ArgVT.getVectorNumElements() > RegisterVT.getVectorNumElements());1277        // We have a vector value which has been split into a vector with1278        // the same scalar type, but fewer elements.  This should handle1279        // all the floating-point vector types.1280        MemVT = RegisterVT;1281      } else if (ArgVT.isVector() &&1282                 ArgVT.getVectorNumElements() == NumRegs) {1283        // This arg has been split so that each element is stored in a separate1284        // register.1285        MemVT = ArgVT.getScalarType();1286      } else if (ArgVT.isExtended()) {1287        // We have an extended type, like i65.1288        MemVT = RegisterVT;1289      } else {1290        unsigned MemoryBits = ArgVT.getStoreSizeInBits() / NumRegs;1291        assert(ArgVT.getStoreSizeInBits() % NumRegs == 0);1292        if (RegisterVT.isInteger()) {1293          MemVT = EVT::getIntegerVT(State.getContext(), MemoryBits);1294        } else if (RegisterVT.isVector()) {1295          assert(!RegisterVT.getScalarType().isFloatingPoint());1296          unsigned NumElements = RegisterVT.getVectorNumElements();1297          assert(MemoryBits % NumElements == 0);1298          // This vector type has been split into another vector type with1299          // a different elements size.1300          EVT ScalarVT = EVT::getIntegerVT(State.getContext(),1301                                           MemoryBits / NumElements);1302          MemVT = EVT::getVectorVT(State.getContext(), ScalarVT, NumElements);1303        } else {1304          llvm_unreachable("cannot deduce memory type.");1305        }1306      }1307 1308      // Convert one element vectors to scalar.1309      if (MemVT.isVector() && MemVT.getVectorNumElements() == 1)1310        MemVT = MemVT.getScalarType();1311 1312      // Round up vec3/vec5 argument.1313      if (MemVT.isVector() && !MemVT.isPow2VectorType()) {1314        MemVT = MemVT.getPow2VectorType(State.getContext());1315      } else if (!MemVT.isSimple() && !MemVT.isVector()) {1316        MemVT = MemVT.getRoundIntegerType(State.getContext());1317      }1318 1319      unsigned PartOffset = 0;1320      for (unsigned i = 0; i != NumRegs; ++i) {1321        State.addLoc(CCValAssign::getCustomMem(InIndex++, RegisterVT,1322                                               BasePartOffset + PartOffset,1323                                               MemVT.getSimpleVT(),1324                                               CCValAssign::Full));1325        PartOffset += MemVT.getStoreSize();1326      }1327    }1328  }1329}1330 1331SDValue AMDGPUTargetLowering::LowerReturn(1332  SDValue Chain, CallingConv::ID CallConv,1333  bool isVarArg,1334  const SmallVectorImpl<ISD::OutputArg> &Outs,1335  const SmallVectorImpl<SDValue> &OutVals,1336  const SDLoc &DL, SelectionDAG &DAG) const {1337  // FIXME: Fails for r600 tests1338  //assert(!isVarArg && Outs.empty() && OutVals.empty() &&1339  // "wave terminate should not have return values");1340  return DAG.getNode(AMDGPUISD::ENDPGM, DL, MVT::Other, Chain);1341}1342 1343//===---------------------------------------------------------------------===//1344// Target specific lowering1345//===---------------------------------------------------------------------===//1346 1347/// Selects the correct CCAssignFn for a given CallingConvention value.1348CCAssignFn *AMDGPUTargetLowering::CCAssignFnForCall(CallingConv::ID CC,1349                                                    bool IsVarArg) {1350  return AMDGPUCallLowering::CCAssignFnForCall(CC, IsVarArg);1351}1352 1353CCAssignFn *AMDGPUTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,1354                                                      bool IsVarArg) {1355  return AMDGPUCallLowering::CCAssignFnForReturn(CC, IsVarArg);1356}1357 1358SDValue AMDGPUTargetLowering::addTokenForArgument(SDValue Chain,1359                                                  SelectionDAG &DAG,1360                                                  MachineFrameInfo &MFI,1361                                                  int ClobberedFI) const {1362  SmallVector<SDValue, 8> ArgChains;1363  int64_t FirstByte = MFI.getObjectOffset(ClobberedFI);1364  int64_t LastByte = FirstByte + MFI.getObjectSize(ClobberedFI) - 1;1365 1366  // Include the original chain at the beginning of the list. When this is1367  // used by target LowerCall hooks, this helps legalize find the1368  // CALLSEQ_BEGIN node.1369  ArgChains.push_back(Chain);1370 1371  // Add a chain value for each stack argument corresponding1372  for (SDNode *U : DAG.getEntryNode().getNode()->users()) {1373    if (LoadSDNode *L = dyn_cast<LoadSDNode>(U)) {1374      if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr())) {1375        if (FI->getIndex() < 0) {1376          int64_t InFirstByte = MFI.getObjectOffset(FI->getIndex());1377          int64_t InLastByte = InFirstByte;1378          InLastByte += MFI.getObjectSize(FI->getIndex()) - 1;1379 1380          if ((InFirstByte <= FirstByte && FirstByte <= InLastByte) ||1381              (FirstByte <= InFirstByte && InFirstByte <= LastByte))1382            ArgChains.push_back(SDValue(L, 1));1383        }1384      }1385    }1386  }1387 1388  // Build a tokenfactor for all the chains.1389  return DAG.getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ArgChains);1390}1391 1392SDValue AMDGPUTargetLowering::lowerUnhandledCall(CallLoweringInfo &CLI,1393                                                 SmallVectorImpl<SDValue> &InVals,1394                                                 StringRef Reason) const {1395  SDValue Callee = CLI.Callee;1396  SelectionDAG &DAG = CLI.DAG;1397 1398  const Function &Fn = DAG.getMachineFunction().getFunction();1399 1400  StringRef FuncName("<unknown>");1401 1402  if (const ExternalSymbolSDNode *G = dyn_cast<ExternalSymbolSDNode>(Callee))1403    FuncName = G->getSymbol();1404  else if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))1405    FuncName = G->getGlobal()->getName();1406 1407  DAG.getContext()->diagnose(1408      DiagnosticInfoUnsupported(Fn, Reason + FuncName, CLI.DL.getDebugLoc()));1409 1410  if (!CLI.IsTailCall) {1411    for (ISD::InputArg &Arg : CLI.Ins)1412      InVals.push_back(DAG.getPOISON(Arg.VT));1413  }1414 1415  return DAG.getEntryNode();1416}1417 1418SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,1419                                        SmallVectorImpl<SDValue> &InVals) const {1420  return lowerUnhandledCall(CLI, InVals, "unsupported call to function ");1421}1422 1423SDValue AMDGPUTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,1424                                                      SelectionDAG &DAG) const {1425  const Function &Fn = DAG.getMachineFunction().getFunction();1426 1427  DAG.getContext()->diagnose(DiagnosticInfoUnsupported(1428      Fn, "unsupported dynamic alloca", SDLoc(Op).getDebugLoc()));1429  auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)};1430  return DAG.getMergeValues(Ops, SDLoc());1431}1432 1433SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op,1434                                             SelectionDAG &DAG) const {1435  switch (Op.getOpcode()) {1436  default:1437    Op->print(errs(), &DAG);1438    llvm_unreachable("Custom lowering code for this "1439                     "instruction is not implemented yet!");1440    break;1441  case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op, DAG);1442  case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);1443  case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG);1444  case ISD::UDIVREM: return LowerUDIVREM(Op, DAG);1445  case ISD::SDIVREM:1446    return LowerSDIVREM(Op, DAG);1447  case ISD::FCEIL: return LowerFCEIL(Op, DAG);1448  case ISD::FTRUNC: return LowerFTRUNC(Op, DAG);1449  case ISD::FRINT: return LowerFRINT(Op, DAG);1450  case ISD::FNEARBYINT: return LowerFNEARBYINT(Op, DAG);1451  case ISD::FROUNDEVEN:1452    return LowerFROUNDEVEN(Op, DAG);1453  case ISD::FROUND: return LowerFROUND(Op, DAG);1454  case ISD::FFLOOR: return LowerFFLOOR(Op, DAG);1455  case ISD::FLOG2:1456    return LowerFLOG2(Op, DAG);1457  case ISD::FLOG:1458  case ISD::FLOG10:1459    return LowerFLOGCommon(Op, DAG);1460  case ISD::FEXP:1461  case ISD::FEXP10:1462    return lowerFEXP(Op, DAG);1463  case ISD::FEXP2:1464    return lowerFEXP2(Op, DAG);1465  case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);1466  case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG);1467  case ISD::FP_TO_FP16: return LowerFP_TO_FP16(Op, DAG);1468  case ISD::FP_TO_SINT:1469  case ISD::FP_TO_UINT:1470    return LowerFP_TO_INT(Op, DAG);1471  case ISD::CTTZ:1472  case ISD::CTTZ_ZERO_UNDEF:1473  case ISD::CTLZ:1474  case ISD::CTLZ_ZERO_UNDEF:1475    return LowerCTLZ_CTTZ(Op, DAG);1476  case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);1477  }1478  return Op;1479}1480 1481void AMDGPUTargetLowering::ReplaceNodeResults(SDNode *N,1482                                              SmallVectorImpl<SDValue> &Results,1483                                              SelectionDAG &DAG) const {1484  switch (N->getOpcode()) {1485  case ISD::SIGN_EXTEND_INREG:1486    // Different parts of legalization seem to interpret which type of1487    // sign_extend_inreg is the one to check for custom lowering. The extended1488    // from type is what really matters, but some places check for custom1489    // lowering of the result type. This results in trying to use1490    // ReplaceNodeResults to sext_in_reg to an illegal type, so we'll just do1491    // nothing here and let the illegal result integer be handled normally.1492    return;1493  case ISD::FLOG2:1494    if (SDValue Lowered = LowerFLOG2(SDValue(N, 0), DAG))1495      Results.push_back(Lowered);1496    return;1497  case ISD::FLOG:1498  case ISD::FLOG10:1499    if (SDValue Lowered = LowerFLOGCommon(SDValue(N, 0), DAG))1500      Results.push_back(Lowered);1501    return;1502  case ISD::FEXP2:1503    if (SDValue Lowered = lowerFEXP2(SDValue(N, 0), DAG))1504      Results.push_back(Lowered);1505    return;1506  case ISD::FEXP:1507  case ISD::FEXP10:1508    if (SDValue Lowered = lowerFEXP(SDValue(N, 0), DAG))1509      Results.push_back(Lowered);1510    return;1511  case ISD::CTLZ:1512  case ISD::CTLZ_ZERO_UNDEF:1513    if (auto Lowered = lowerCTLZResults(SDValue(N, 0u), DAG))1514      Results.push_back(Lowered);1515    return;1516  default:1517    return;1518  }1519}1520 1521SDValue AMDGPUTargetLowering::LowerGlobalAddress(AMDGPUMachineFunction* MFI,1522                                                 SDValue Op,1523                                                 SelectionDAG &DAG) const {1524 1525  const DataLayout &DL = DAG.getDataLayout();1526  GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);1527  const GlobalValue *GV = G->getGlobal();1528 1529  if (!MFI->isModuleEntryFunction()) {1530    auto IsNamedBarrier = AMDGPU::isNamedBarrier(*cast<GlobalVariable>(GV));1531    if (std::optional<uint32_t> Address =1532            AMDGPUMachineFunction::getLDSAbsoluteAddress(*GV)) {1533      if (IsNamedBarrier) {1534        unsigned BarCnt = DL.getTypeAllocSize(GV->getValueType()) / 16;1535        MFI->recordNumNamedBarriers(Address.value(), BarCnt);1536      }1537      return DAG.getConstant(*Address, SDLoc(Op), Op.getValueType());1538    } else if (IsNamedBarrier) {1539      llvm_unreachable("named barrier should have an assigned address");1540    }1541  }1542 1543  if (G->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||1544      G->getAddressSpace() == AMDGPUAS::REGION_ADDRESS) {1545    if (!MFI->isModuleEntryFunction() &&1546        GV->getName() != "llvm.amdgcn.module.lds" &&1547        !AMDGPU::isNamedBarrier(*cast<GlobalVariable>(GV))) {1548      SDLoc DL(Op);1549      const Function &Fn = DAG.getMachineFunction().getFunction();1550      DAG.getContext()->diagnose(DiagnosticInfoUnsupported(1551          Fn, "local memory global used by non-kernel function",1552          DL.getDebugLoc(), DS_Warning));1553 1554      // We currently don't have a way to correctly allocate LDS objects that1555      // aren't directly associated with a kernel. We do force inlining of1556      // functions that use local objects. However, if these dead functions are1557      // not eliminated, we don't want a compile time error. Just emit a warning1558      // and a trap, since there should be no callable path here.1559      SDValue Trap = DAG.getNode(ISD::TRAP, DL, MVT::Other, DAG.getEntryNode());1560      SDValue OutputChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,1561                                        Trap, DAG.getRoot());1562      DAG.setRoot(OutputChain);1563      return DAG.getPOISON(Op.getValueType());1564    }1565 1566    // XXX: What does the value of G->getOffset() mean?1567    assert(G->getOffset() == 0 &&1568         "Do not know what to do with an non-zero offset");1569 1570    // TODO: We could emit code to handle the initialization somewhere.1571    // We ignore the initializer for now and legalize it to allow selection.1572    // The initializer will anyway get errored out during assembly emission.1573    unsigned Offset = MFI->allocateLDSGlobal(DL, *cast<GlobalVariable>(GV));1574    return DAG.getConstant(Offset, SDLoc(Op), Op.getValueType());1575  }1576  return SDValue();1577}1578 1579SDValue AMDGPUTargetLowering::LowerCONCAT_VECTORS(SDValue Op,1580                                                  SelectionDAG &DAG) const {1581  SmallVector<SDValue, 8> Args;1582  SDLoc SL(Op);1583 1584  EVT VT = Op.getValueType();1585  if (VT.getVectorElementType().getSizeInBits() < 32) {1586    unsigned OpBitSize = Op.getOperand(0).getValueType().getSizeInBits();1587    if (OpBitSize >= 32 && OpBitSize % 32 == 0) {1588      unsigned NewNumElt = OpBitSize / 32;1589      EVT NewEltVT = (NewNumElt == 1) ? MVT::i321590                                      : EVT::getVectorVT(*DAG.getContext(),1591                                                         MVT::i32, NewNumElt);1592      for (const SDUse &U : Op->ops()) {1593        SDValue In = U.get();1594        SDValue NewIn = DAG.getNode(ISD::BITCAST, SL, NewEltVT, In);1595        if (NewNumElt > 1)1596          DAG.ExtractVectorElements(NewIn, Args);1597        else1598          Args.push_back(NewIn);1599      }1600 1601      EVT NewVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,1602                                   NewNumElt * Op.getNumOperands());1603      SDValue BV = DAG.getBuildVector(NewVT, SL, Args);1604      return DAG.getNode(ISD::BITCAST, SL, VT, BV);1605    }1606  }1607 1608  for (const SDUse &U : Op->ops())1609    DAG.ExtractVectorElements(U.get(), Args);1610 1611  return DAG.getBuildVector(Op.getValueType(), SL, Args);1612}1613 1614SDValue AMDGPUTargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op,1615                                                     SelectionDAG &DAG) const {1616  SDLoc SL(Op);1617  SmallVector<SDValue, 8> Args;1618  unsigned Start = Op.getConstantOperandVal(1);1619  EVT VT = Op.getValueType();1620  EVT SrcVT = Op.getOperand(0).getValueType();1621 1622  if (VT.getScalarSizeInBits() == 16 && Start % 2 == 0) {1623    unsigned NumElt = VT.getVectorNumElements();1624    unsigned NumSrcElt = SrcVT.getVectorNumElements();1625    assert(NumElt % 2 == 0 && NumSrcElt % 2 == 0 && "expect legal types");1626 1627    // Extract 32-bit registers at a time.1628    EVT NewSrcVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumSrcElt / 2);1629    EVT NewVT = NumElt == 21630                    ? MVT::i321631                    : EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElt / 2);1632    SDValue Tmp = DAG.getNode(ISD::BITCAST, SL, NewSrcVT, Op.getOperand(0));1633 1634    DAG.ExtractVectorElements(Tmp, Args, Start / 2, NumElt / 2);1635    if (NumElt == 2)1636      Tmp = Args[0];1637    else1638      Tmp = DAG.getBuildVector(NewVT, SL, Args);1639 1640    return DAG.getNode(ISD::BITCAST, SL, VT, Tmp);1641  }1642 1643  DAG.ExtractVectorElements(Op.getOperand(0), Args, Start,1644                            VT.getVectorNumElements());1645 1646  return DAG.getBuildVector(Op.getValueType(), SL, Args);1647}1648 1649// TODO: Handle fabs too1650static SDValue peekFNeg(SDValue Val) {1651  if (Val.getOpcode() == ISD::FNEG)1652    return Val.getOperand(0);1653 1654  return Val;1655}1656 1657static SDValue peekFPSignOps(SDValue Val) {1658  if (Val.getOpcode() == ISD::FNEG)1659    Val = Val.getOperand(0);1660  if (Val.getOpcode() == ISD::FABS)1661    Val = Val.getOperand(0);1662  if (Val.getOpcode() == ISD::FCOPYSIGN)1663    Val = Val.getOperand(0);1664  return Val;1665}1666 1667SDValue AMDGPUTargetLowering::combineFMinMaxLegacyImpl(1668    const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True,1669    SDValue False, SDValue CC, DAGCombinerInfo &DCI) const {1670  SelectionDAG &DAG = DCI.DAG;1671  ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();1672  switch (CCOpcode) {1673  case ISD::SETOEQ:1674  case ISD::SETONE:1675  case ISD::SETUNE:1676  case ISD::SETNE:1677  case ISD::SETUEQ:1678  case ISD::SETEQ:1679  case ISD::SETFALSE:1680  case ISD::SETFALSE2:1681  case ISD::SETTRUE:1682  case ISD::SETTRUE2:1683  case ISD::SETUO:1684  case ISD::SETO:1685    break;1686  case ISD::SETULE:1687  case ISD::SETULT: {1688    if (LHS == True)1689      return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);1690    return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);1691  }1692  case ISD::SETOLE:1693  case ISD::SETOLT:1694  case ISD::SETLE:1695  case ISD::SETLT: {1696    // Ordered. Assume ordered for undefined.1697 1698    // Only do this after legalization to avoid interfering with other combines1699    // which might occur.1700    if (DCI.getDAGCombineLevel() < AfterLegalizeDAG &&1701        !DCI.isCalledByLegalizer())1702      return SDValue();1703 1704    // We need to permute the operands to get the correct NaN behavior. The1705    // selected operand is the second one based on the failing compare with NaN,1706    // so permute it based on the compare type the hardware uses.1707    if (LHS == True)1708      return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);1709    return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);1710  }1711  case ISD::SETUGE:1712  case ISD::SETUGT: {1713    if (LHS == True)1714      return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);1715    return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);1716  }1717  case ISD::SETGT:1718  case ISD::SETGE:1719  case ISD::SETOGE:1720  case ISD::SETOGT: {1721    if (DCI.getDAGCombineLevel() < AfterLegalizeDAG &&1722        !DCI.isCalledByLegalizer())1723      return SDValue();1724 1725    if (LHS == True)1726      return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);1727    return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);1728  }1729  case ISD::SETCC_INVALID:1730    llvm_unreachable("Invalid setcc condcode!");1731  }1732  return SDValue();1733}1734 1735/// Generate Min/Max node1736SDValue AMDGPUTargetLowering::combineFMinMaxLegacy(const SDLoc &DL, EVT VT,1737                                                   SDValue LHS, SDValue RHS,1738                                                   SDValue True, SDValue False,1739                                                   SDValue CC,1740                                                   DAGCombinerInfo &DCI) const {1741  if ((LHS == True && RHS == False) || (LHS == False && RHS == True))1742    return combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, True, False, CC, DCI);1743 1744  SelectionDAG &DAG = DCI.DAG;1745 1746  // If we can't directly match this, try to see if we can fold an fneg to1747  // match.1748 1749  ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);1750  ConstantFPSDNode *CFalse = dyn_cast<ConstantFPSDNode>(False);1751  SDValue NegTrue = peekFNeg(True);1752 1753  // Undo the combine foldFreeOpFromSelect does if it helps us match the1754  // fmin/fmax.1755  //1756  // select (fcmp olt (lhs, K)), (fneg lhs), -K1757  // -> fneg (fmin_legacy lhs, K)1758  //1759  // TODO: Use getNegatedExpression1760  if (LHS == NegTrue && CFalse && CRHS) {1761    APFloat NegRHS = neg(CRHS->getValueAPF());1762    if (NegRHS == CFalse->getValueAPF()) {1763      SDValue Combined =1764          combineFMinMaxLegacyImpl(DL, VT, LHS, RHS, NegTrue, False, CC, DCI);1765      if (Combined)1766        return DAG.getNode(ISD::FNEG, DL, VT, Combined);1767      return SDValue();1768    }1769  }1770 1771  return SDValue();1772}1773 1774std::pair<SDValue, SDValue>1775AMDGPUTargetLowering::split64BitValue(SDValue Op, SelectionDAG &DAG) const {1776  SDLoc SL(Op);1777 1778  SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);1779 1780  const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);1781  const SDValue One = DAG.getConstant(1, SL, MVT::i32);1782 1783  SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);1784  SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);1785 1786  return std::pair(Lo, Hi);1787}1788 1789SDValue AMDGPUTargetLowering::getLoHalf64(SDValue Op, SelectionDAG &DAG) const {1790  SDLoc SL(Op);1791 1792  SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);1793  const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);1794  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);1795}1796 1797SDValue AMDGPUTargetLowering::getHiHalf64(SDValue Op, SelectionDAG &DAG) const {1798  SDLoc SL(Op);1799 1800  SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);1801  const SDValue One = DAG.getConstant(1, SL, MVT::i32);1802  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);1803}1804 1805// Split a vector type into two parts. The first part is a power of two vector.1806// The second part is whatever is left over, and is a scalar if it would1807// otherwise be a 1-vector.1808std::pair<EVT, EVT>1809AMDGPUTargetLowering::getSplitDestVTs(const EVT &VT, SelectionDAG &DAG) const {1810  EVT LoVT, HiVT;1811  EVT EltVT = VT.getVectorElementType();1812  unsigned NumElts = VT.getVectorNumElements();1813  unsigned LoNumElts = PowerOf2Ceil((NumElts + 1) / 2);1814  LoVT = EVT::getVectorVT(*DAG.getContext(), EltVT, LoNumElts);1815  HiVT = NumElts - LoNumElts == 11816             ? EltVT1817             : EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts - LoNumElts);1818  return std::pair(LoVT, HiVT);1819}1820 1821// Split a vector value into two parts of types LoVT and HiVT. HiVT could be1822// scalar.1823std::pair<SDValue, SDValue>1824AMDGPUTargetLowering::splitVector(const SDValue &N, const SDLoc &DL,1825                                  const EVT &LoVT, const EVT &HiVT,1826                                  SelectionDAG &DAG) const {1827  EVT VT = N.getValueType();1828  assert(LoVT.getVectorNumElements() +1829                 (HiVT.isVector() ? HiVT.getVectorNumElements() : 1) <=1830             VT.getVectorNumElements() &&1831         "More vector elements requested than available!");1832  SDValue Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, N,1833                           DAG.getVectorIdxConstant(0, DL));1834 1835  unsigned LoNumElts = LoVT.getVectorNumElements();1836 1837  if (HiVT.isVector()) {1838    unsigned HiNumElts = HiVT.getVectorNumElements();1839    if ((VT.getVectorNumElements() % HiNumElts) == 0) {1840      // Avoid creating an extract_subvector with an index that isn't a multiple1841      // of the result type.1842      SDValue Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, N,1843                               DAG.getConstant(LoNumElts, DL, MVT::i32));1844      return {Lo, Hi};1845    }1846 1847    SmallVector<SDValue, 8> Elts;1848    DAG.ExtractVectorElements(N, Elts, /*Start=*/LoNumElts,1849                              /*Count=*/HiNumElts);1850    SDValue Hi = DAG.getBuildVector(HiVT, DL, Elts);1851    return {Lo, Hi};1852  }1853 1854  SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, HiVT, N,1855                           DAG.getVectorIdxConstant(LoNumElts, DL));1856  return {Lo, Hi};1857}1858 1859SDValue AMDGPUTargetLowering::SplitVectorLoad(const SDValue Op,1860                                              SelectionDAG &DAG) const {1861  LoadSDNode *Load = cast<LoadSDNode>(Op);1862  EVT VT = Op.getValueType();1863  SDLoc SL(Op);1864 1865 1866  // If this is a 2 element vector, we really want to scalarize and not create1867  // weird 1 element vectors.1868  if (VT.getVectorNumElements() == 2) {1869    SDValue Ops[2];1870    std::tie(Ops[0], Ops[1]) = scalarizeVectorLoad(Load, DAG);1871    return DAG.getMergeValues(Ops, SL);1872  }1873 1874  SDValue BasePtr = Load->getBasePtr();1875  EVT MemVT = Load->getMemoryVT();1876 1877  const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();1878 1879  EVT LoVT, HiVT;1880  EVT LoMemVT, HiMemVT;1881  SDValue Lo, Hi;1882 1883  std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);1884  std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);1885  std::tie(Lo, Hi) = splitVector(Op, SL, LoVT, HiVT, DAG);1886 1887  unsigned Size = LoMemVT.getStoreSize();1888  Align BaseAlign = Load->getAlign();1889  Align HiAlign = commonAlignment(BaseAlign, Size);1890 1891  SDValue LoLoad = DAG.getExtLoad(1892      Load->getExtensionType(), SL, LoVT, Load->getChain(), BasePtr, SrcValue,1893      LoMemVT, BaseAlign, Load->getMemOperand()->getFlags(), Load->getAAInfo());1894  SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Size));1895  SDValue HiLoad = DAG.getExtLoad(1896      Load->getExtensionType(), SL, HiVT, Load->getChain(), HiPtr,1897      SrcValue.getWithOffset(LoMemVT.getStoreSize()), HiMemVT, HiAlign,1898      Load->getMemOperand()->getFlags(), Load->getAAInfo());1899 1900  SDValue Join;1901  if (LoVT == HiVT) {1902    // This is the case that the vector is power of two so was evenly split.1903    Join = DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, LoLoad, HiLoad);1904  } else {1905    Join = DAG.getNode(ISD::INSERT_SUBVECTOR, SL, VT, DAG.getPOISON(VT), LoLoad,1906                       DAG.getVectorIdxConstant(0, SL));1907    Join = DAG.getNode(1908        HiVT.isVector() ? ISD::INSERT_SUBVECTOR : ISD::INSERT_VECTOR_ELT, SL,1909        VT, Join, HiLoad,1910        DAG.getVectorIdxConstant(LoVT.getVectorNumElements(), SL));1911  }1912 1913  SDValue Ops[] = {Join, DAG.getNode(ISD::TokenFactor, SL, MVT::Other,1914                                     LoLoad.getValue(1), HiLoad.getValue(1))};1915 1916  return DAG.getMergeValues(Ops, SL);1917}1918 1919SDValue AMDGPUTargetLowering::WidenOrSplitVectorLoad(SDValue Op,1920                                                     SelectionDAG &DAG) const {1921  LoadSDNode *Load = cast<LoadSDNode>(Op);1922  EVT VT = Op.getValueType();1923  SDValue BasePtr = Load->getBasePtr();1924  EVT MemVT = Load->getMemoryVT();1925  SDLoc SL(Op);1926  const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();1927  Align BaseAlign = Load->getAlign();1928  unsigned NumElements = MemVT.getVectorNumElements();1929 1930  // Widen from vec3 to vec4 when the load is at least 8-byte aligned1931  // or 16-byte fully dereferenceable. Otherwise, split the vector load.1932  if (NumElements != 3 ||1933      (BaseAlign < Align(8) &&1934       !SrcValue.isDereferenceable(16, *DAG.getContext(), DAG.getDataLayout())))1935    return SplitVectorLoad(Op, DAG);1936 1937  assert(NumElements == 3);1938 1939  EVT WideVT =1940      EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(), 4);1941  EVT WideMemVT =1942      EVT::getVectorVT(*DAG.getContext(), MemVT.getVectorElementType(), 4);1943  SDValue WideLoad = DAG.getExtLoad(1944      Load->getExtensionType(), SL, WideVT, Load->getChain(), BasePtr, SrcValue,1945      WideMemVT, BaseAlign, Load->getMemOperand()->getFlags());1946  return DAG.getMergeValues(1947      {DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, VT, WideLoad,1948                   DAG.getVectorIdxConstant(0, SL)),1949       WideLoad.getValue(1)},1950      SL);1951}1952 1953SDValue AMDGPUTargetLowering::SplitVectorStore(SDValue Op,1954                                               SelectionDAG &DAG) const {1955  StoreSDNode *Store = cast<StoreSDNode>(Op);1956  SDValue Val = Store->getValue();1957  EVT VT = Val.getValueType();1958 1959  // If this is a 2 element vector, we really want to scalarize and not create1960  // weird 1 element vectors.1961  if (VT.getVectorNumElements() == 2)1962    return scalarizeVectorStore(Store, DAG);1963 1964  EVT MemVT = Store->getMemoryVT();1965  SDValue Chain = Store->getChain();1966  SDValue BasePtr = Store->getBasePtr();1967  SDLoc SL(Op);1968 1969  EVT LoVT, HiVT;1970  EVT LoMemVT, HiMemVT;1971  SDValue Lo, Hi;1972 1973  std::tie(LoVT, HiVT) = getSplitDestVTs(VT, DAG);1974  std::tie(LoMemVT, HiMemVT) = getSplitDestVTs(MemVT, DAG);1975  std::tie(Lo, Hi) = splitVector(Val, SL, LoVT, HiVT, DAG);1976 1977  SDValue HiPtr = DAG.getObjectPtrOffset(SL, BasePtr, LoMemVT.getStoreSize());1978 1979  const MachinePointerInfo &SrcValue = Store->getMemOperand()->getPointerInfo();1980  Align BaseAlign = Store->getAlign();1981  unsigned Size = LoMemVT.getStoreSize();1982  Align HiAlign = commonAlignment(BaseAlign, Size);1983 1984  SDValue LoStore =1985      DAG.getTruncStore(Chain, SL, Lo, BasePtr, SrcValue, LoMemVT, BaseAlign,1986                        Store->getMemOperand()->getFlags(), Store->getAAInfo());1987  SDValue HiStore = DAG.getTruncStore(1988      Chain, SL, Hi, HiPtr, SrcValue.getWithOffset(Size), HiMemVT, HiAlign,1989      Store->getMemOperand()->getFlags(), Store->getAAInfo());1990 1991  return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, LoStore, HiStore);1992}1993 1994// This is a shortcut for integer division because we have fast i32<->f321995// conversions, and fast f32 reciprocal instructions. The fractional part of a1996// float is enough to accurately represent up to a 24-bit signed integer.1997SDValue AMDGPUTargetLowering::LowerDIVREM24(SDValue Op, SelectionDAG &DAG,1998                                            bool Sign) const {1999  SDLoc DL(Op);2000  EVT VT = Op.getValueType();2001  SDValue LHS = Op.getOperand(0);2002  SDValue RHS = Op.getOperand(1);2003  MVT IntVT = MVT::i32;2004  MVT FltVT = MVT::f32;2005 2006  unsigned LHSSignBits = DAG.ComputeNumSignBits(LHS);2007  if (LHSSignBits < 9)2008    return SDValue();2009 2010  unsigned RHSSignBits = DAG.ComputeNumSignBits(RHS);2011  if (RHSSignBits < 9)2012    return SDValue();2013 2014  unsigned BitSize = VT.getSizeInBits();2015  unsigned SignBits = std::min(LHSSignBits, RHSSignBits);2016  unsigned DivBits = BitSize - SignBits;2017  if (Sign)2018    ++DivBits;2019 2020  ISD::NodeType ToFp = Sign ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;2021  ISD::NodeType ToInt = Sign ? ISD::FP_TO_SINT : ISD::FP_TO_UINT;2022 2023  SDValue jq = DAG.getConstant(1, DL, IntVT);2024 2025  if (Sign) {2026    // char|short jq = ia ^ ib;2027    jq = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);2028 2029    // jq = jq >> (bitsize - 2)2030    jq = DAG.getNode(ISD::SRA, DL, VT, jq,2031                     DAG.getConstant(BitSize - 2, DL, VT));2032 2033    // jq = jq | 0x12034    jq = DAG.getNode(ISD::OR, DL, VT, jq, DAG.getConstant(1, DL, VT));2035  }2036 2037  // int ia = (int)LHS;2038  SDValue ia = LHS;2039 2040  // int ib, (int)RHS;2041  SDValue ib = RHS;2042 2043  // float fa = (float)ia;2044  SDValue fa = DAG.getNode(ToFp, DL, FltVT, ia);2045 2046  // float fb = (float)ib;2047  SDValue fb = DAG.getNode(ToFp, DL, FltVT, ib);2048 2049  SDValue fq = DAG.getNode(ISD::FMUL, DL, FltVT,2050                           fa, DAG.getNode(AMDGPUISD::RCP, DL, FltVT, fb));2051 2052  // fq = trunc(fq);2053  fq = DAG.getNode(ISD::FTRUNC, DL, FltVT, fq);2054 2055  // float fqneg = -fq;2056  SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FltVT, fq);2057 2058  MachineFunction &MF = DAG.getMachineFunction();2059 2060  bool UseFmadFtz = false;2061  if (Subtarget->isGCN()) {2062    const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();2063    UseFmadFtz =2064        MFI->getMode().FP32Denormals != DenormalMode::getPreserveSign();2065  }2066 2067  // float fr = mad(fqneg, fb, fa);2068  unsigned OpCode = !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA2069                    : UseFmadFtz ? (unsigned)AMDGPUISD::FMAD_FTZ2070                                 : (unsigned)ISD::FMAD;2071  SDValue fr = DAG.getNode(OpCode, DL, FltVT, fqneg, fb, fa);2072 2073  // int iq = (int)fq;2074  SDValue iq = DAG.getNode(ToInt, DL, IntVT, fq);2075 2076  // fr = fabs(fr);2077  fr = DAG.getNode(ISD::FABS, DL, FltVT, fr);2078 2079  // fb = fabs(fb);2080  fb = DAG.getNode(ISD::FABS, DL, FltVT, fb);2081 2082  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);2083 2084  // int cv = fr >= fb;2085  SDValue cv = DAG.getSetCC(DL, SetCCVT, fr, fb, ISD::SETOGE);2086 2087  // jq = (cv ? jq : 0);2088  jq = DAG.getNode(ISD::SELECT, DL, VT, cv, jq, DAG.getConstant(0, DL, VT));2089 2090  // dst = iq + jq;2091  SDValue Div = DAG.getNode(ISD::ADD, DL, VT, iq, jq);2092 2093  // Rem needs compensation, it's easier to recompute it2094  SDValue Rem = DAG.getNode(ISD::MUL, DL, VT, Div, RHS);2095  Rem = DAG.getNode(ISD::SUB, DL, VT, LHS, Rem);2096 2097  // Truncate to number of bits this divide really is.2098  if (Sign) {2099    SDValue InRegSize2100      = DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), DivBits));2101    Div = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Div, InRegSize);2102    Rem = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Rem, InRegSize);2103  } else {2104    SDValue TruncMask = DAG.getConstant((UINT64_C(1) << DivBits) - 1, DL, VT);2105    Div = DAG.getNode(ISD::AND, DL, VT, Div, TruncMask);2106    Rem = DAG.getNode(ISD::AND, DL, VT, Rem, TruncMask);2107  }2108 2109  return DAG.getMergeValues({ Div, Rem }, DL);2110}2111 2112void AMDGPUTargetLowering::LowerUDIVREM64(SDValue Op,2113                                      SelectionDAG &DAG,2114                                      SmallVectorImpl<SDValue> &Results) const {2115  SDLoc DL(Op);2116  EVT VT = Op.getValueType();2117 2118  assert(VT == MVT::i64 && "LowerUDIVREM64 expects an i64");2119 2120  EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());2121 2122  SDValue One = DAG.getConstant(1, DL, HalfVT);2123  SDValue Zero = DAG.getConstant(0, DL, HalfVT);2124 2125  //HiLo split2126  SDValue LHS_Lo, LHS_Hi;2127  SDValue LHS = Op.getOperand(0);2128  std::tie(LHS_Lo, LHS_Hi) = DAG.SplitScalar(LHS, DL, HalfVT, HalfVT);2129 2130  SDValue RHS_Lo, RHS_Hi;2131  SDValue RHS = Op.getOperand(1);2132  std::tie(RHS_Lo, RHS_Hi) = DAG.SplitScalar(RHS, DL, HalfVT, HalfVT);2133 2134  if (DAG.MaskedValueIsZero(RHS, APInt::getHighBitsSet(64, 32)) &&2135      DAG.MaskedValueIsZero(LHS, APInt::getHighBitsSet(64, 32))) {2136 2137    SDValue Res = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),2138                              LHS_Lo, RHS_Lo);2139 2140    SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(0), Zero});2141    SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(1), Zero});2142 2143    Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV));2144    Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM));2145    return;2146  }2147 2148  if (isTypeLegal(MVT::i64)) {2149    // The algorithm here is based on ideas from "Software Integer Division",2150    // Tom Rodeheffer, August 2008.2151 2152    MachineFunction &MF = DAG.getMachineFunction();2153    const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();2154 2155    // Compute denominator reciprocal.2156    unsigned FMAD =2157        !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA2158        : MFI->getMode().FP32Denormals == DenormalMode::getPreserveSign()2159            ? (unsigned)ISD::FMAD2160            : (unsigned)AMDGPUISD::FMAD_FTZ;2161 2162    SDValue Cvt_Lo = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Lo);2163    SDValue Cvt_Hi = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f32, RHS_Hi);2164    SDValue Mad1 = DAG.getNode(FMAD, DL, MVT::f32, Cvt_Hi,2165      DAG.getConstantFP(APInt(32, 0x4f800000).bitsToFloat(), DL, MVT::f32),2166      Cvt_Lo);2167    SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, DL, MVT::f32, Mad1);2168    SDValue Mul1 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Rcp,2169      DAG.getConstantFP(APInt(32, 0x5f7ffffc).bitsToFloat(), DL, MVT::f32));2170    SDValue Mul2 = DAG.getNode(ISD::FMUL, DL, MVT::f32, Mul1,2171      DAG.getConstantFP(APInt(32, 0x2f800000).bitsToFloat(), DL, MVT::f32));2172    SDValue Trunc = DAG.getNode(ISD::FTRUNC, DL, MVT::f32, Mul2);2173    SDValue Mad2 = DAG.getNode(FMAD, DL, MVT::f32, Trunc,2174      DAG.getConstantFP(APInt(32, 0xcf800000).bitsToFloat(), DL, MVT::f32),2175      Mul1);2176    SDValue Rcp_Lo = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Mad2);2177    SDValue Rcp_Hi = DAG.getNode(ISD::FP_TO_UINT, DL, HalfVT, Trunc);2178    SDValue Rcp64 = DAG.getBitcast(VT,2179                        DAG.getBuildVector(MVT::v2i32, DL, {Rcp_Lo, Rcp_Hi}));2180 2181    SDValue Zero64 = DAG.getConstant(0, DL, VT);2182    SDValue One64  = DAG.getConstant(1, DL, VT);2183    SDValue Zero1 = DAG.getConstant(0, DL, MVT::i1);2184    SDVTList HalfCarryVT = DAG.getVTList(HalfVT, MVT::i1);2185 2186    // First round of UNR (Unsigned integer Newton-Raphson).2187    SDValue Neg_RHS = DAG.getNode(ISD::SUB, DL, VT, Zero64, RHS);2188    SDValue Mullo1 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Rcp64);2189    SDValue Mulhi1 = DAG.getNode(ISD::MULHU, DL, VT, Rcp64, Mullo1);2190    SDValue Mulhi1_Lo, Mulhi1_Hi;2191    std::tie(Mulhi1_Lo, Mulhi1_Hi) =2192        DAG.SplitScalar(Mulhi1, DL, HalfVT, HalfVT);2193    SDValue Add1_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Lo,2194                                  Mulhi1_Lo, Zero1);2195    SDValue Add1_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Rcp_Hi,2196                                  Mulhi1_Hi, Add1_Lo.getValue(1));2197    SDValue Add1 = DAG.getBitcast(VT,2198                        DAG.getBuildVector(MVT::v2i32, DL, {Add1_Lo, Add1_Hi}));2199 2200    // Second round of UNR.2201    SDValue Mullo2 = DAG.getNode(ISD::MUL, DL, VT, Neg_RHS, Add1);2202    SDValue Mulhi2 = DAG.getNode(ISD::MULHU, DL, VT, Add1, Mullo2);2203    SDValue Mulhi2_Lo, Mulhi2_Hi;2204    std::tie(Mulhi2_Lo, Mulhi2_Hi) =2205        DAG.SplitScalar(Mulhi2, DL, HalfVT, HalfVT);2206    SDValue Add2_Lo = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Lo,2207                                  Mulhi2_Lo, Zero1);2208    SDValue Add2_Hi = DAG.getNode(ISD::UADDO_CARRY, DL, HalfCarryVT, Add1_Hi,2209                                  Mulhi2_Hi, Add2_Lo.getValue(1));2210    SDValue Add2 = DAG.getBitcast(VT,2211                        DAG.getBuildVector(MVT::v2i32, DL, {Add2_Lo, Add2_Hi}));2212 2213    SDValue Mulhi3 = DAG.getNode(ISD::MULHU, DL, VT, LHS, Add2);2214 2215    SDValue Mul3 = DAG.getNode(ISD::MUL, DL, VT, RHS, Mulhi3);2216 2217    SDValue Mul3_Lo, Mul3_Hi;2218    std::tie(Mul3_Lo, Mul3_Hi) = DAG.SplitScalar(Mul3, DL, HalfVT, HalfVT);2219    SDValue Sub1_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Lo,2220                                  Mul3_Lo, Zero1);2221    SDValue Sub1_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, LHS_Hi,2222                                  Mul3_Hi, Sub1_Lo.getValue(1));2223    SDValue Sub1_Mi = DAG.getNode(ISD::SUB, DL, HalfVT, LHS_Hi, Mul3_Hi);2224    SDValue Sub1 = DAG.getBitcast(VT,2225                        DAG.getBuildVector(MVT::v2i32, DL, {Sub1_Lo, Sub1_Hi}));2226 2227    SDValue MinusOne = DAG.getConstant(0xffffffffu, DL, HalfVT);2228    SDValue C1 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, MinusOne, Zero,2229                                 ISD::SETUGE);2230    SDValue C2 = DAG.getSelectCC(DL, Sub1_Lo, RHS_Lo, MinusOne, Zero,2231                                 ISD::SETUGE);2232    SDValue C3 = DAG.getSelectCC(DL, Sub1_Hi, RHS_Hi, C2, C1, ISD::SETEQ);2233 2234    // TODO: Here and below portions of the code can be enclosed into if/endif.2235    // Currently control flow is unconditional and we have 4 selects after2236    // potential endif to substitute PHIs.2237 2238    // if C3 != 0 ...2239    SDValue Sub2_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Lo,2240                                  RHS_Lo, Zero1);2241    SDValue Sub2_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub1_Mi,2242                                  RHS_Hi, Sub1_Lo.getValue(1));2243    SDValue Sub2_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,2244                                  Zero, Sub2_Lo.getValue(1));2245    SDValue Sub2 = DAG.getBitcast(VT,2246                        DAG.getBuildVector(MVT::v2i32, DL, {Sub2_Lo, Sub2_Hi}));2247 2248    SDValue Add3 = DAG.getNode(ISD::ADD, DL, VT, Mulhi3, One64);2249 2250    SDValue C4 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, MinusOne, Zero,2251                                 ISD::SETUGE);2252    SDValue C5 = DAG.getSelectCC(DL, Sub2_Lo, RHS_Lo, MinusOne, Zero,2253                                 ISD::SETUGE);2254    SDValue C6 = DAG.getSelectCC(DL, Sub2_Hi, RHS_Hi, C5, C4, ISD::SETEQ);2255 2256    // if (C6 != 0)2257    SDValue Add4 = DAG.getNode(ISD::ADD, DL, VT, Add3, One64);2258 2259    SDValue Sub3_Lo = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Lo,2260                                  RHS_Lo, Zero1);2261    SDValue Sub3_Mi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub2_Mi,2262                                  RHS_Hi, Sub2_Lo.getValue(1));2263    SDValue Sub3_Hi = DAG.getNode(ISD::USUBO_CARRY, DL, HalfCarryVT, Sub3_Mi,2264                                  Zero, Sub3_Lo.getValue(1));2265    SDValue Sub3 = DAG.getBitcast(VT,2266                        DAG.getBuildVector(MVT::v2i32, DL, {Sub3_Lo, Sub3_Hi}));2267 2268    // endif C62269    // endif C32270 2271    SDValue Sel1 = DAG.getSelectCC(DL, C6, Zero, Add4, Add3, ISD::SETNE);2272    SDValue Div  = DAG.getSelectCC(DL, C3, Zero, Sel1, Mulhi3, ISD::SETNE);2273 2274    SDValue Sel2 = DAG.getSelectCC(DL, C6, Zero, Sub3, Sub2, ISD::SETNE);2275    SDValue Rem  = DAG.getSelectCC(DL, C3, Zero, Sel2, Sub1, ISD::SETNE);2276 2277    Results.push_back(Div);2278    Results.push_back(Rem);2279 2280    return;2281  }2282 2283  // r600 expandion.2284  // Get Speculative values2285  SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);2286  SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);2287 2288  SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, Zero, REM_Part, LHS_Hi, ISD::SETEQ);2289  SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {REM_Lo, Zero});2290  REM = DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM);2291 2292  SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, Zero, DIV_Part, Zero, ISD::SETEQ);2293  SDValue DIV_Lo = Zero;2294 2295  const unsigned halfBitWidth = HalfVT.getSizeInBits();2296 2297  for (unsigned i = 0; i < halfBitWidth; ++i) {2298    const unsigned bitPos = halfBitWidth - i - 1;2299    SDValue POS = DAG.getConstant(bitPos, DL, HalfVT);2300    // Get value of high bit2301    SDValue HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);2302    HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, One);2303    HBit = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, HBit);2304 2305    // Shift2306    REM = DAG.getNode(ISD::SHL, DL, VT, REM, DAG.getConstant(1, DL, VT));2307    // Add LHS high bit2308    REM = DAG.getNode(ISD::OR, DL, VT, REM, HBit);2309 2310    SDValue BIT = DAG.getConstant(1ULL << bitPos, DL, HalfVT);2311    SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, Zero, ISD::SETUGE);2312 2313    DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);2314 2315    // Update REM2316    SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);2317    REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETUGE);2318  }2319 2320  SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {DIV_Lo, DIV_Hi});2321  DIV = DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV);2322  Results.push_back(DIV);2323  Results.push_back(REM);2324}2325 2326SDValue AMDGPUTargetLowering::LowerUDIVREM(SDValue Op,2327                                           SelectionDAG &DAG) const {2328  SDLoc DL(Op);2329  EVT VT = Op.getValueType();2330 2331  if (VT == MVT::i64) {2332    SmallVector<SDValue, 2> Results;2333    LowerUDIVREM64(Op, DAG, Results);2334    return DAG.getMergeValues(Results, DL);2335  }2336 2337  if (VT == MVT::i32) {2338    if (SDValue Res = LowerDIVREM24(Op, DAG, false))2339      return Res;2340  }2341 2342  SDValue X = Op.getOperand(0);2343  SDValue Y = Op.getOperand(1);2344 2345  // See AMDGPUCodeGenPrepare::expandDivRem32 for a description of the2346  // algorithm used here.2347 2348  // Initial estimate of inv(y).2349  SDValue Z = DAG.getNode(AMDGPUISD::URECIP, DL, VT, Y);2350 2351  // One round of UNR.2352  SDValue NegY = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Y);2353  SDValue NegYZ = DAG.getNode(ISD::MUL, DL, VT, NegY, Z);2354  Z = DAG.getNode(ISD::ADD, DL, VT, Z,2355                  DAG.getNode(ISD::MULHU, DL, VT, Z, NegYZ));2356 2357  // Quotient/remainder estimate.2358  SDValue Q = DAG.getNode(ISD::MULHU, DL, VT, X, Z);2359  SDValue R =2360      DAG.getNode(ISD::SUB, DL, VT, X, DAG.getNode(ISD::MUL, DL, VT, Q, Y));2361 2362  // First quotient/remainder refinement.2363  EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);2364  SDValue One = DAG.getConstant(1, DL, VT);2365  SDValue Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);2366  Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,2367                  DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);2368  R = DAG.getNode(ISD::SELECT, DL, VT, Cond,2369                  DAG.getNode(ISD::SUB, DL, VT, R, Y), R);2370 2371  // Second quotient/remainder refinement.2372  Cond = DAG.getSetCC(DL, CCVT, R, Y, ISD::SETUGE);2373  Q = DAG.getNode(ISD::SELECT, DL, VT, Cond,2374                  DAG.getNode(ISD::ADD, DL, VT, Q, One), Q);2375  R = DAG.getNode(ISD::SELECT, DL, VT, Cond,2376                  DAG.getNode(ISD::SUB, DL, VT, R, Y), R);2377 2378  return DAG.getMergeValues({Q, R}, DL);2379}2380 2381SDValue AMDGPUTargetLowering::LowerSDIVREM(SDValue Op,2382                                           SelectionDAG &DAG) const {2383  SDLoc DL(Op);2384  EVT VT = Op.getValueType();2385 2386  SDValue LHS = Op.getOperand(0);2387  SDValue RHS = Op.getOperand(1);2388 2389  SDValue Zero = DAG.getConstant(0, DL, VT);2390  SDValue NegOne = DAG.getAllOnesConstant(DL, VT);2391 2392  if (VT == MVT::i32) {2393    if (SDValue Res = LowerDIVREM24(Op, DAG, true))2394      return Res;2395  }2396 2397  if (VT == MVT::i64 &&2398      DAG.ComputeNumSignBits(LHS) > 32 &&2399      DAG.ComputeNumSignBits(RHS) > 32) {2400    EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());2401 2402    //HiLo split2403    SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, Zero);2404    SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, Zero);2405    SDValue DIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),2406                                 LHS_Lo, RHS_Lo);2407    SDValue Res[2] = {2408      DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(0)),2409      DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(1))2410    };2411    return DAG.getMergeValues(Res, DL);2412  }2413 2414  SDValue LHSign = DAG.getSelectCC(DL, LHS, Zero, NegOne, Zero, ISD::SETLT);2415  SDValue RHSign = DAG.getSelectCC(DL, RHS, Zero, NegOne, Zero, ISD::SETLT);2416  SDValue DSign = DAG.getNode(ISD::XOR, DL, VT, LHSign, RHSign);2417  SDValue RSign = LHSign; // Remainder sign is the same as LHS2418 2419  LHS = DAG.getNode(ISD::ADD, DL, VT, LHS, LHSign);2420  RHS = DAG.getNode(ISD::ADD, DL, VT, RHS, RHSign);2421 2422  LHS = DAG.getNode(ISD::XOR, DL, VT, LHS, LHSign);2423  RHS = DAG.getNode(ISD::XOR, DL, VT, RHS, RHSign);2424 2425  SDValue Div = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT), LHS, RHS);2426  SDValue Rem = Div.getValue(1);2427 2428  Div = DAG.getNode(ISD::XOR, DL, VT, Div, DSign);2429  Rem = DAG.getNode(ISD::XOR, DL, VT, Rem, RSign);2430 2431  Div = DAG.getNode(ISD::SUB, DL, VT, Div, DSign);2432  Rem = DAG.getNode(ISD::SUB, DL, VT, Rem, RSign);2433 2434  SDValue Res[2] = {2435    Div,2436    Rem2437  };2438  return DAG.getMergeValues(Res, DL);2439}2440 2441SDValue AMDGPUTargetLowering::LowerFCEIL(SDValue Op, SelectionDAG &DAG) const {2442  SDLoc SL(Op);2443  SDValue Src = Op.getOperand(0);2444 2445  // result = trunc(src)2446  // if (src > 0.0 && src != result)2447  //   result += 1.02448 2449  SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);2450 2451  const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);2452  const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);2453 2454  EVT SetCCVT =2455      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);2456 2457  SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOGT);2458  SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);2459  SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);2460 2461  SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, One, Zero);2462  // TODO: Should this propagate fast-math-flags?2463  return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);2464}2465 2466static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL,2467                                  SelectionDAG &DAG) {2468  const unsigned FractBits = 52;2469  const unsigned ExpBits = 11;2470 2471  SDValue ExpPart = DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,2472                                Hi,2473                                DAG.getConstant(FractBits - 32, SL, MVT::i32),2474                                DAG.getConstant(ExpBits, SL, MVT::i32));2475  SDValue Exp = DAG.getNode(ISD::SUB, SL, MVT::i32, ExpPart,2476                            DAG.getConstant(1023, SL, MVT::i32));2477 2478  return Exp;2479}2480 2481SDValue AMDGPUTargetLowering::LowerFTRUNC(SDValue Op, SelectionDAG &DAG) const {2482  SDLoc SL(Op);2483  SDValue Src = Op.getOperand(0);2484 2485  assert(Op.getValueType() == MVT::f64);2486 2487  const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);2488 2489  // Extract the upper half, since this is where we will find the sign and2490  // exponent.2491  SDValue Hi = getHiHalf64(Src, DAG);2492 2493  SDValue Exp = extractF64Exponent(Hi, SL, DAG);2494 2495  const unsigned FractBits = 52;2496 2497  // Extract the sign bit.2498  const SDValue SignBitMask = DAG.getConstant(UINT32_C(1) << 31, SL, MVT::i32);2499  SDValue SignBit = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, SignBitMask);2500 2501  // Extend back to 64-bits.2502  SDValue SignBit64 = DAG.getBuildVector(MVT::v2i32, SL, {Zero, SignBit});2503  SignBit64 = DAG.getNode(ISD::BITCAST, SL, MVT::i64, SignBit64);2504 2505  SDValue BcInt = DAG.getNode(ISD::BITCAST, SL, MVT::i64, Src);2506  const SDValue FractMask2507    = DAG.getConstant((UINT64_C(1) << FractBits) - 1, SL, MVT::i64);2508 2509  SDValue Shr = DAG.getNode(ISD::SRA, SL, MVT::i64, FractMask, Exp);2510  SDValue Not = DAG.getNOT(SL, Shr, MVT::i64);2511  SDValue Tmp0 = DAG.getNode(ISD::AND, SL, MVT::i64, BcInt, Not);2512 2513  EVT SetCCVT =2514      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i32);2515 2516  const SDValue FiftyOne = DAG.getConstant(FractBits - 1, SL, MVT::i32);2517 2518  SDValue ExpLt0 = DAG.getSetCC(SL, SetCCVT, Exp, Zero, ISD::SETLT);2519  SDValue ExpGt51 = DAG.getSetCC(SL, SetCCVT, Exp, FiftyOne, ISD::SETGT);2520 2521  SDValue Tmp1 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpLt0, SignBit64, Tmp0);2522  SDValue Tmp2 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpGt51, BcInt, Tmp1);2523 2524  return DAG.getNode(ISD::BITCAST, SL, MVT::f64, Tmp2);2525}2526 2527SDValue AMDGPUTargetLowering::LowerFROUNDEVEN(SDValue Op,2528                                              SelectionDAG &DAG) const {2529  SDLoc SL(Op);2530  SDValue Src = Op.getOperand(0);2531 2532  assert(Op.getValueType() == MVT::f64);2533 2534  APFloat C1Val(APFloat::IEEEdouble(), "0x1.0p+52");2535  SDValue C1 = DAG.getConstantFP(C1Val, SL, MVT::f64);2536  SDValue CopySign = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f64, C1, Src);2537 2538  // TODO: Should this propagate fast-math-flags?2539 2540  SDValue Tmp1 = DAG.getNode(ISD::FADD, SL, MVT::f64, Src, CopySign);2541  SDValue Tmp2 = DAG.getNode(ISD::FSUB, SL, MVT::f64, Tmp1, CopySign);2542 2543  SDValue Fabs = DAG.getNode(ISD::FABS, SL, MVT::f64, Src);2544 2545  APFloat C2Val(APFloat::IEEEdouble(), "0x1.fffffffffffffp+51");2546  SDValue C2 = DAG.getConstantFP(C2Val, SL, MVT::f64);2547 2548  EVT SetCCVT =2549      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);2550  SDValue Cond = DAG.getSetCC(SL, SetCCVT, Fabs, C2, ISD::SETOGT);2551 2552  return DAG.getSelect(SL, MVT::f64, Cond, Src, Tmp2);2553}2554 2555SDValue AMDGPUTargetLowering::LowerFNEARBYINT(SDValue Op,2556                                              SelectionDAG &DAG) const {2557  // FNEARBYINT and FRINT are the same, except in their handling of FP2558  // exceptions. Those aren't really meaningful for us, and OpenCL only has2559  // rint, so just treat them as equivalent.2560  return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), Op.getValueType(),2561                     Op.getOperand(0));2562}2563 2564SDValue AMDGPUTargetLowering::LowerFRINT(SDValue Op, SelectionDAG &DAG) const {2565  auto VT = Op.getValueType();2566  auto Arg = Op.getOperand(0u);2567  return DAG.getNode(ISD::FROUNDEVEN, SDLoc(Op), VT, Arg);2568}2569 2570// XXX - May require not supporting f32 denormals?2571 2572// Don't handle v2f16. The extra instructions to scalarize and repack around the2573// compare and vselect end up producing worse code than scalarizing the whole2574// operation.2575SDValue AMDGPUTargetLowering::LowerFROUND(SDValue Op, SelectionDAG &DAG) const {2576  SDLoc SL(Op);2577  SDValue X = Op.getOperand(0);2578  EVT VT = Op.getValueType();2579 2580  SDValue T = DAG.getNode(ISD::FTRUNC, SL, VT, X);2581 2582  // TODO: Should this propagate fast-math-flags?2583 2584  SDValue Diff = DAG.getNode(ISD::FSUB, SL, VT, X, T);2585 2586  SDValue AbsDiff = DAG.getNode(ISD::FABS, SL, VT, Diff);2587 2588  const SDValue Zero = DAG.getConstantFP(0.0, SL, VT);2589  const SDValue One = DAG.getConstantFP(1.0, SL, VT);2590 2591  EVT SetCCVT =2592      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);2593 2594  const SDValue Half = DAG.getConstantFP(0.5, SL, VT);2595  SDValue Cmp = DAG.getSetCC(SL, SetCCVT, AbsDiff, Half, ISD::SETOGE);2596  SDValue OneOrZeroFP = DAG.getNode(ISD::SELECT, SL, VT, Cmp, One, Zero);2597 2598  SDValue SignedOffset = DAG.getNode(ISD::FCOPYSIGN, SL, VT, OneOrZeroFP, X);2599  return DAG.getNode(ISD::FADD, SL, VT, T, SignedOffset);2600}2601 2602SDValue AMDGPUTargetLowering::LowerFFLOOR(SDValue Op, SelectionDAG &DAG) const {2603  SDLoc SL(Op);2604  SDValue Src = Op.getOperand(0);2605 2606  // result = trunc(src);2607  // if (src < 0.0 && src != result)2608  //   result += -1.0.2609 2610  SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);2611 2612  const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);2613  const SDValue NegOne = DAG.getConstantFP(-1.0, SL, MVT::f64);2614 2615  EVT SetCCVT =2616      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);2617 2618  SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOLT);2619  SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);2620  SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);2621 2622  SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, NegOne, Zero);2623  // TODO: Should this propagate fast-math-flags?2624  return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);2625}2626 2627/// Return true if it's known that \p Src can never be an f32 denormal value.2628static bool valueIsKnownNeverF32Denorm(SDValue Src) {2629  switch (Src.getOpcode()) {2630  case ISD::FP_EXTEND:2631    return Src.getOperand(0).getValueType() == MVT::f16;2632  case ISD::FP16_TO_FP:2633  case ISD::FFREXP:2634    return true;2635  case ISD::INTRINSIC_WO_CHAIN: {2636    unsigned IntrinsicID = Src.getConstantOperandVal(0);2637    switch (IntrinsicID) {2638    case Intrinsic::amdgcn_frexp_mant:2639      return true;2640    default:2641      return false;2642    }2643  }2644  default:2645    return false;2646  }2647 2648  llvm_unreachable("covered opcode switch");2649}2650 2651bool AMDGPUTargetLowering::allowApproxFunc(const SelectionDAG &DAG,2652                                           SDNodeFlags Flags) {2653  return Flags.hasApproximateFuncs();2654}2655 2656bool AMDGPUTargetLowering::needsDenormHandlingF32(const SelectionDAG &DAG,2657                                                  SDValue Src,2658                                                  SDNodeFlags Flags) {2659  return !valueIsKnownNeverF32Denorm(Src) &&2660         DAG.getMachineFunction()2661                 .getDenormalMode(APFloat::IEEEsingle())2662                 .Input != DenormalMode::PreserveSign;2663}2664 2665SDValue AMDGPUTargetLowering::getIsLtSmallestNormal(SelectionDAG &DAG,2666                                                    SDValue Src,2667                                                    SDNodeFlags Flags) const {2668  SDLoc SL(Src);2669  EVT VT = Src.getValueType();2670  const fltSemantics &Semantics = VT.getFltSemantics();2671  SDValue SmallestNormal =2672      DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);2673 2674  // Want to scale denormals up, but negatives and 0 work just as well on the2675  // scaled path.2676  SDValue IsLtSmallestNormal = DAG.getSetCC(2677      SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,2678      SmallestNormal, ISD::SETOLT);2679 2680  return IsLtSmallestNormal;2681}2682 2683SDValue AMDGPUTargetLowering::getIsFinite(SelectionDAG &DAG, SDValue Src,2684                                          SDNodeFlags Flags) const {2685  SDLoc SL(Src);2686  EVT VT = Src.getValueType();2687  const fltSemantics &Semantics = VT.getFltSemantics();2688  SDValue Inf = DAG.getConstantFP(APFloat::getInf(Semantics), SL, VT);2689 2690  SDValue Fabs = DAG.getNode(ISD::FABS, SL, VT, Src, Flags);2691  SDValue IsFinite = DAG.getSetCC(2692      SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Fabs,2693      Inf, ISD::SETOLT);2694  return IsFinite;2695}2696 2697/// If denormal handling is required return the scaled input to FLOG2, and the2698/// check for denormal range. Otherwise, return null values.2699std::pair<SDValue, SDValue>2700AMDGPUTargetLowering::getScaledLogInput(SelectionDAG &DAG, const SDLoc SL,2701                                        SDValue Src, SDNodeFlags Flags) const {2702  if (!needsDenormHandlingF32(DAG, Src, Flags))2703    return {};2704 2705  MVT VT = MVT::f32;2706  const fltSemantics &Semantics = APFloat::IEEEsingle();2707  SDValue SmallestNormal =2708      DAG.getConstantFP(APFloat::getSmallestNormalized(Semantics), SL, VT);2709 2710  SDValue IsLtSmallestNormal = DAG.getSetCC(2711      SL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT), Src,2712      SmallestNormal, ISD::SETOLT);2713 2714  SDValue Scale32 = DAG.getConstantFP(0x1.0p+32, SL, VT);2715  SDValue One = DAG.getConstantFP(1.0, SL, VT);2716  SDValue ScaleFactor =2717      DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, Scale32, One, Flags);2718 2719  SDValue ScaledInput = DAG.getNode(ISD::FMUL, SL, VT, Src, ScaleFactor, Flags);2720  return {ScaledInput, IsLtSmallestNormal};2721}2722 2723SDValue AMDGPUTargetLowering::LowerFLOG2(SDValue Op, SelectionDAG &DAG) const {2724  // v_log_f32 is good enough for OpenCL, except it doesn't handle denormals.2725  // If we have to handle denormals, scale up the input and adjust the result.2726 2727  // scaled = x * (is_denormal ? 0x1.0p+32 : 1.0)2728  // log2 = amdgpu_log2 - (is_denormal ? 32.0 : 0.0)2729 2730  SDLoc SL(Op);2731  EVT VT = Op.getValueType();2732  SDValue Src = Op.getOperand(0);2733  SDNodeFlags Flags = Op->getFlags();2734 2735  if (VT == MVT::f16) {2736    // Nothing in half is a denormal when promoted to f32.2737    assert(!Subtarget->has16BitInsts());2738    SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);2739    SDValue Log = DAG.getNode(AMDGPUISD::LOG, SL, MVT::f32, Ext, Flags);2740    return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,2741                       DAG.getTargetConstant(0, SL, MVT::i32), Flags);2742  }2743 2744  auto [ScaledInput, IsLtSmallestNormal] =2745      getScaledLogInput(DAG, SL, Src, Flags);2746  if (!ScaledInput)2747    return DAG.getNode(AMDGPUISD::LOG, SL, VT, Src, Flags);2748 2749  SDValue Log2 = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);2750 2751  SDValue ThirtyTwo = DAG.getConstantFP(32.0, SL, VT);2752  SDValue Zero = DAG.getConstantFP(0.0, SL, VT);2753  SDValue ResultOffset =2754      DAG.getNode(ISD::SELECT, SL, VT, IsLtSmallestNormal, ThirtyTwo, Zero);2755  return DAG.getNode(ISD::FSUB, SL, VT, Log2, ResultOffset, Flags);2756}2757 2758static SDValue getMad(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue X,2759                      SDValue Y, SDValue C, SDNodeFlags Flags = SDNodeFlags()) {2760  SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Y, Flags);2761  return DAG.getNode(ISD::FADD, SL, VT, Mul, C, Flags);2762}2763 2764SDValue AMDGPUTargetLowering::LowerFLOGCommon(SDValue Op,2765                                              SelectionDAG &DAG) const {2766  SDValue X = Op.getOperand(0);2767  EVT VT = Op.getValueType();2768  SDNodeFlags Flags = Op->getFlags();2769  SDLoc DL(Op);2770 2771  const bool IsLog10 = Op.getOpcode() == ISD::FLOG10;2772  assert(IsLog10 || Op.getOpcode() == ISD::FLOG);2773 2774  const auto &Options = getTargetMachine().Options;2775  if (VT == MVT::f16 || Flags.hasApproximateFuncs()) {2776 2777    if (VT == MVT::f16 && !Subtarget->has16BitInsts()) {2778      // Log and multiply in f32 is good enough for f16.2779      X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X, Flags);2780    }2781 2782    SDValue Lowered = LowerFLOGUnsafe(X, DL, DAG, IsLog10, Flags);2783    if (VT == MVT::f16 && !Subtarget->has16BitInsts()) {2784      return DAG.getNode(ISD::FP_ROUND, DL, VT, Lowered,2785                         DAG.getTargetConstant(0, DL, MVT::i32), Flags);2786    }2787 2788    return Lowered;2789  }2790 2791  auto [ScaledInput, IsScaled] = getScaledLogInput(DAG, DL, X, Flags);2792  if (ScaledInput)2793    X = ScaledInput;2794 2795  SDValue Y = DAG.getNode(AMDGPUISD::LOG, DL, VT, X, Flags);2796 2797  SDValue R;2798  if (Subtarget->hasFastFMAF32()) {2799    // c+cc are ln(2)/ln(10) to more than 49 bits2800    const float c_log10 = 0x1.344134p-2f;2801    const float cc_log10 = 0x1.09f79ep-26f;2802 2803    // c + cc is ln(2) to more than 49 bits2804    const float c_log = 0x1.62e42ep-1f;2805    const float cc_log = 0x1.efa39ep-25f;2806 2807    SDValue C = DAG.getConstantFP(IsLog10 ? c_log10 : c_log, DL, VT);2808    SDValue CC = DAG.getConstantFP(IsLog10 ? cc_log10 : cc_log, DL, VT);2809 2810    R = DAG.getNode(ISD::FMUL, DL, VT, Y, C, Flags);2811    SDValue NegR = DAG.getNode(ISD::FNEG, DL, VT, R, Flags);2812    SDValue FMA0 = DAG.getNode(ISD::FMA, DL, VT, Y, C, NegR, Flags);2813    SDValue FMA1 = DAG.getNode(ISD::FMA, DL, VT, Y, CC, FMA0, Flags);2814    R = DAG.getNode(ISD::FADD, DL, VT, R, FMA1, Flags);2815  } else {2816    // ch+ct is ln(2)/ln(10) to more than 36 bits2817    const float ch_log10 = 0x1.344000p-2f;2818    const float ct_log10 = 0x1.3509f6p-18f;2819 2820    // ch + ct is ln(2) to more than 36 bits2821    const float ch_log = 0x1.62e000p-1f;2822    const float ct_log = 0x1.0bfbe8p-15f;2823 2824    SDValue CH = DAG.getConstantFP(IsLog10 ? ch_log10 : ch_log, DL, VT);2825    SDValue CT = DAG.getConstantFP(IsLog10 ? ct_log10 : ct_log, DL, VT);2826 2827    SDValue YAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Y);2828    SDValue MaskConst = DAG.getConstant(0xfffff000, DL, MVT::i32);2829    SDValue YHInt = DAG.getNode(ISD::AND, DL, MVT::i32, YAsInt, MaskConst);2830    SDValue YH = DAG.getNode(ISD::BITCAST, DL, MVT::f32, YHInt);2831    SDValue YT = DAG.getNode(ISD::FSUB, DL, VT, Y, YH, Flags);2832 2833    SDValue YTCT = DAG.getNode(ISD::FMUL, DL, VT, YT, CT, Flags);2834    SDValue Mad0 = getMad(DAG, DL, VT, YH, CT, YTCT, Flags);2835    SDValue Mad1 = getMad(DAG, DL, VT, YT, CH, Mad0, Flags);2836    R = getMad(DAG, DL, VT, YH, CH, Mad1);2837  }2838 2839  const bool IsFiniteOnly =2840      (Flags.hasNoNaNs() || Options.NoNaNsFPMath) && Flags.hasNoInfs();2841 2842  // TODO: Check if known finite from source value.2843  if (!IsFiniteOnly) {2844    SDValue IsFinite = getIsFinite(DAG, Y, Flags);2845    R = DAG.getNode(ISD::SELECT, DL, VT, IsFinite, R, Y, Flags);2846  }2847 2848  if (IsScaled) {2849    SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);2850    SDValue ShiftK =2851        DAG.getConstantFP(IsLog10 ? 0x1.344136p+3f : 0x1.62e430p+4f, DL, VT);2852    SDValue Shift =2853        DAG.getNode(ISD::SELECT, DL, VT, IsScaled, ShiftK, Zero, Flags);2854    R = DAG.getNode(ISD::FSUB, DL, VT, R, Shift, Flags);2855  }2856 2857  return R;2858}2859 2860SDValue AMDGPUTargetLowering::LowerFLOG10(SDValue Op, SelectionDAG &DAG) const {2861  return LowerFLOGCommon(Op, DAG);2862}2863 2864// Do f32 fast math expansion for flog2 or flog10. This is accurate enough for a2865// promote f16 operation.2866SDValue AMDGPUTargetLowering::LowerFLOGUnsafe(SDValue Src, const SDLoc &SL,2867                                              SelectionDAG &DAG, bool IsLog10,2868                                              SDNodeFlags Flags) const {2869  EVT VT = Src.getValueType();2870  unsigned LogOp =2871      VT == MVT::f32 ? (unsigned)AMDGPUISD::LOG : (unsigned)ISD::FLOG2;2872 2873  double Log2BaseInverted =2874      IsLog10 ? numbers::ln2 / numbers::ln10 : numbers::ln2;2875 2876  if (VT == MVT::f32) {2877    auto [ScaledInput, IsScaled] = getScaledLogInput(DAG, SL, Src, Flags);2878    if (ScaledInput) {2879      SDValue LogSrc = DAG.getNode(AMDGPUISD::LOG, SL, VT, ScaledInput, Flags);2880      SDValue ScaledResultOffset =2881          DAG.getConstantFP(-32.0 * Log2BaseInverted, SL, VT);2882 2883      SDValue Zero = DAG.getConstantFP(0.0f, SL, VT);2884 2885      SDValue ResultOffset = DAG.getNode(ISD::SELECT, SL, VT, IsScaled,2886                                         ScaledResultOffset, Zero, Flags);2887 2888      SDValue Log2Inv = DAG.getConstantFP(Log2BaseInverted, SL, VT);2889 2890      if (Subtarget->hasFastFMAF32())2891        return DAG.getNode(ISD::FMA, SL, VT, LogSrc, Log2Inv, ResultOffset,2892                           Flags);2893      SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, LogSrc, Log2Inv, Flags);2894      return DAG.getNode(ISD::FADD, SL, VT, Mul, ResultOffset);2895    }2896  }2897 2898  SDValue Log2Operand = DAG.getNode(LogOp, SL, VT, Src, Flags);2899  SDValue Log2BaseInvertedOperand = DAG.getConstantFP(Log2BaseInverted, SL, VT);2900 2901  return DAG.getNode(ISD::FMUL, SL, VT, Log2Operand, Log2BaseInvertedOperand,2902                     Flags);2903}2904 2905SDValue AMDGPUTargetLowering::lowerFEXP2(SDValue Op, SelectionDAG &DAG) const {2906  // v_exp_f32 is good enough for OpenCL, except it doesn't handle denormals.2907  // If we have to handle denormals, scale up the input and adjust the result.2908 2909  SDLoc SL(Op);2910  EVT VT = Op.getValueType();2911  SDValue Src = Op.getOperand(0);2912  SDNodeFlags Flags = Op->getFlags();2913 2914  if (VT == MVT::f16) {2915    // Nothing in half is a denormal when promoted to f32.2916    assert(!Subtarget->has16BitInsts());2917    SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src, Flags);2918    SDValue Log = DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Ext, Flags);2919    return DAG.getNode(ISD::FP_ROUND, SL, VT, Log,2920                       DAG.getTargetConstant(0, SL, MVT::i32), Flags);2921  }2922 2923  assert(VT == MVT::f32);2924 2925  if (!needsDenormHandlingF32(DAG, Src, Flags))2926    return DAG.getNode(AMDGPUISD::EXP, SL, MVT::f32, Src, Flags);2927 2928  // bool needs_scaling = x < -0x1.f80000p+6f;2929  // v_exp_f32(x + (s ? 0x1.0p+6f : 0.0f)) * (s ? 0x1.0p-64f : 1.0f);2930 2931  // -nextafter(128.0, -1)2932  SDValue RangeCheckConst = DAG.getConstantFP(-0x1.f80000p+6f, SL, VT);2933 2934  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);2935 2936  SDValue NeedsScaling =2937      DAG.getSetCC(SL, SetCCVT, Src, RangeCheckConst, ISD::SETOLT);2938 2939  SDValue SixtyFour = DAG.getConstantFP(0x1.0p+6f, SL, VT);2940  SDValue Zero = DAG.getConstantFP(0.0, SL, VT);2941 2942  SDValue AddOffset =2943      DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, SixtyFour, Zero);2944 2945  SDValue AddInput = DAG.getNode(ISD::FADD, SL, VT, Src, AddOffset, Flags);2946  SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, AddInput, Flags);2947 2948  SDValue TwoExpNeg64 = DAG.getConstantFP(0x1.0p-64f, SL, VT);2949  SDValue One = DAG.getConstantFP(1.0, SL, VT);2950  SDValue ResultScale =2951      DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, TwoExpNeg64, One);2952 2953  return DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScale, Flags);2954}2955 2956SDValue AMDGPUTargetLowering::lowerFEXPUnsafe(SDValue X, const SDLoc &SL,2957                                              SelectionDAG &DAG,2958                                              SDNodeFlags Flags) const {2959  EVT VT = X.getValueType();2960  const SDValue Log2E = DAG.getConstantFP(numbers::log2e, SL, VT);2961 2962  if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags)) {2963    // exp2(M_LOG2E_F * f);2964    SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, X, Log2E, Flags);2965    return DAG.getNode(VT == MVT::f32 ? (unsigned)AMDGPUISD::EXP2966                                      : (unsigned)ISD::FEXP2,2967                       SL, VT, Mul, Flags);2968  }2969 2970  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);2971 2972  SDValue Threshold = DAG.getConstantFP(-0x1.5d58a0p+6f, SL, VT);2973  SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);2974 2975  SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+6f, SL, VT);2976 2977  SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);2978 2979  SDValue AdjustedX =2980      DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);2981 2982  SDValue ExpInput = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, Log2E, Flags);2983 2984  SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, ExpInput, Flags);2985 2986  SDValue ResultScaleFactor = DAG.getConstantFP(0x1.969d48p-93f, SL, VT);2987  SDValue AdjustedResult =2988      DAG.getNode(ISD::FMUL, SL, VT, Exp2, ResultScaleFactor, Flags);2989 2990  return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, Exp2,2991                     Flags);2992}2993 2994/// Emit approx-funcs appropriate lowering for exp10. inf/nan should still be2995/// handled correctly.2996SDValue AMDGPUTargetLowering::lowerFEXP10Unsafe(SDValue X, const SDLoc &SL,2997                                                SelectionDAG &DAG,2998                                                SDNodeFlags Flags) const {2999  const EVT VT = X.getValueType();3000  const unsigned Exp2Op = VT == MVT::f32 ? static_cast<unsigned>(AMDGPUISD::EXP)3001                                         : static_cast<unsigned>(ISD::FEXP2);3002 3003  if (VT != MVT::f32 || !needsDenormHandlingF32(DAG, X, Flags)) {3004    // exp2(x * 0x1.a92000p+1f) * exp2(x * 0x1.4f0978p-11f);3005    SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);3006    SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);3007 3008    SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, X, K0, Flags);3009    SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);3010    SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, X, K1, Flags);3011    SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);3012    return DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1);3013  }3014 3015  // bool s = x < -0x1.2f7030p+5f;3016  // x += s ? 0x1.0p+5f : 0.0f;3017  // exp10 = exp2(x * 0x1.a92000p+1f) *3018  //        exp2(x * 0x1.4f0978p-11f) *3019  //        (s ? 0x1.9f623ep-107f : 1.0f);3020 3021  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);3022 3023  SDValue Threshold = DAG.getConstantFP(-0x1.2f7030p+5f, SL, VT);3024  SDValue NeedsScaling = DAG.getSetCC(SL, SetCCVT, X, Threshold, ISD::SETOLT);3025 3026  SDValue ScaleOffset = DAG.getConstantFP(0x1.0p+5f, SL, VT);3027  SDValue ScaledX = DAG.getNode(ISD::FADD, SL, VT, X, ScaleOffset, Flags);3028  SDValue AdjustedX =3029      DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, ScaledX, X);3030 3031  SDValue K0 = DAG.getConstantFP(0x1.a92000p+1f, SL, VT);3032  SDValue K1 = DAG.getConstantFP(0x1.4f0978p-11f, SL, VT);3033 3034  SDValue Mul0 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K0, Flags);3035  SDValue Exp2_0 = DAG.getNode(Exp2Op, SL, VT, Mul0, Flags);3036  SDValue Mul1 = DAG.getNode(ISD::FMUL, SL, VT, AdjustedX, K1, Flags);3037  SDValue Exp2_1 = DAG.getNode(Exp2Op, SL, VT, Mul1, Flags);3038 3039  SDValue MulExps = DAG.getNode(ISD::FMUL, SL, VT, Exp2_0, Exp2_1, Flags);3040 3041  SDValue ResultScaleFactor = DAG.getConstantFP(0x1.9f623ep-107f, SL, VT);3042  SDValue AdjustedResult =3043      DAG.getNode(ISD::FMUL, SL, VT, MulExps, ResultScaleFactor, Flags);3044 3045  return DAG.getNode(ISD::SELECT, SL, VT, NeedsScaling, AdjustedResult, MulExps,3046                     Flags);3047}3048 3049SDValue AMDGPUTargetLowering::lowerFEXP(SDValue Op, SelectionDAG &DAG) const {3050  EVT VT = Op.getValueType();3051  SDLoc SL(Op);3052  SDValue X = Op.getOperand(0);3053  SDNodeFlags Flags = Op->getFlags();3054  const bool IsExp10 = Op.getOpcode() == ISD::FEXP10;3055 3056  if (VT.getScalarType() == MVT::f16) {3057    // v_exp_f16 (fmul x, log2e)3058    if (allowApproxFunc(DAG, Flags)) // TODO: Does this really require fast?3059      return lowerFEXPUnsafe(X, SL, DAG, Flags);3060 3061    if (VT.isVector())3062      return SDValue();3063 3064    // exp(f16 x) ->3065    //   fptrunc (v_exp_f32 (fmul (fpext x), log2e))3066 3067    // Nothing in half is a denormal when promoted to f32.3068    SDValue Ext = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, X, Flags);3069    SDValue Lowered = lowerFEXPUnsafe(Ext, SL, DAG, Flags);3070    return DAG.getNode(ISD::FP_ROUND, SL, VT, Lowered,3071                       DAG.getTargetConstant(0, SL, MVT::i32), Flags);3072  }3073 3074  assert(VT == MVT::f32);3075 3076  // TODO: Interpret allowApproxFunc as ignoring DAZ. This is currently copying3077  // library behavior. Also, is known-not-daz source sufficient?3078  if (allowApproxFunc(DAG, Flags)) {3079    return IsExp10 ? lowerFEXP10Unsafe(X, SL, DAG, Flags)3080                   : lowerFEXPUnsafe(X, SL, DAG, Flags);3081  }3082 3083  //    Algorithm:3084  //3085  //    e^x = 2^(x/ln(2)) = 2^(x*(64/ln(2))/64)3086  //3087  //    x*(64/ln(2)) = n + f, |f| <= 0.5, n is integer3088  //    n = 64*m + j,   0 <= j < 643089  //3090  //    e^x = 2^((64*m + j + f)/64)3091  //        = (2^m) * (2^(j/64)) * 2^(f/64)3092  //        = (2^m) * (2^(j/64)) * e^(f*(ln(2)/64))3093  //3094  //    f = x*(64/ln(2)) - n3095  //    r = f*(ln(2)/64) = x - n*(ln(2)/64)3096  //3097  //    e^x = (2^m) * (2^(j/64)) * e^r3098  //3099  //    (2^(j/64)) is precomputed3100  //3101  //    e^r = 1 + r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!3102  //    e^r = 1 + q3103  //3104  //    q = r + (r^2)/2! + (r^3)/3! + (r^4)/4! + (r^5)/5!3105  //3106  //    e^x = (2^m) * ( (2^(j/64)) + q*(2^(j/64)) )3107  SDNodeFlags FlagsNoContract = Flags;3108  FlagsNoContract.setAllowContract(false);3109 3110  SDValue PH, PL;3111  if (Subtarget->hasFastFMAF32()) {3112    const float c_exp = numbers::log2ef;3113    const float cc_exp = 0x1.4ae0bep-26f; // c+cc are 49 bits3114    const float c_exp10 = 0x1.a934f0p+1f;3115    const float cc_exp10 = 0x1.2f346ep-24f;3116 3117    SDValue C = DAG.getConstantFP(IsExp10 ? c_exp10 : c_exp, SL, VT);3118    SDValue CC = DAG.getConstantFP(IsExp10 ? cc_exp10 : cc_exp, SL, VT);3119 3120    PH = DAG.getNode(ISD::FMUL, SL, VT, X, C, Flags);3121    SDValue NegPH = DAG.getNode(ISD::FNEG, SL, VT, PH, Flags);3122    SDValue FMA0 = DAG.getNode(ISD::FMA, SL, VT, X, C, NegPH, Flags);3123    PL = DAG.getNode(ISD::FMA, SL, VT, X, CC, FMA0, Flags);3124  } else {3125    const float ch_exp = 0x1.714000p+0f;3126    const float cl_exp = 0x1.47652ap-12f; // ch + cl are 36 bits3127 3128    const float ch_exp10 = 0x1.a92000p+1f;3129    const float cl_exp10 = 0x1.4f0978p-11f;3130 3131    SDValue CH = DAG.getConstantFP(IsExp10 ? ch_exp10 : ch_exp, SL, VT);3132    SDValue CL = DAG.getConstantFP(IsExp10 ? cl_exp10 : cl_exp, SL, VT);3133 3134    SDValue XAsInt = DAG.getNode(ISD::BITCAST, SL, MVT::i32, X);3135    SDValue MaskConst = DAG.getConstant(0xfffff000, SL, MVT::i32);3136    SDValue XHAsInt = DAG.getNode(ISD::AND, SL, MVT::i32, XAsInt, MaskConst);3137    SDValue XH = DAG.getNode(ISD::BITCAST, SL, VT, XHAsInt);3138    SDValue XL = DAG.getNode(ISD::FSUB, SL, VT, X, XH, Flags);3139 3140    PH = DAG.getNode(ISD::FMUL, SL, VT, XH, CH, Flags);3141 3142    SDValue XLCL = DAG.getNode(ISD::FMUL, SL, VT, XL, CL, Flags);3143    SDValue Mad0 = getMad(DAG, SL, VT, XL, CH, XLCL, Flags);3144    PL = getMad(DAG, SL, VT, XH, CL, Mad0, Flags);3145  }3146 3147  SDValue E = DAG.getNode(ISD::FROUNDEVEN, SL, VT, PH, Flags);3148 3149  // It is unsafe to contract this fsub into the PH multiply.3150  SDValue PHSubE = DAG.getNode(ISD::FSUB, SL, VT, PH, E, FlagsNoContract);3151 3152  SDValue A = DAG.getNode(ISD::FADD, SL, VT, PHSubE, PL, Flags);3153  SDValue IntE = DAG.getNode(ISD::FP_TO_SINT, SL, MVT::i32, E);3154  SDValue Exp2 = DAG.getNode(AMDGPUISD::EXP, SL, VT, A, Flags);3155 3156  SDValue R = DAG.getNode(ISD::FLDEXP, SL, VT, Exp2, IntE, Flags);3157 3158  SDValue UnderflowCheckConst =3159      DAG.getConstantFP(IsExp10 ? -0x1.66d3e8p+5f : -0x1.9d1da0p+6f, SL, VT);3160 3161  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);3162  SDValue Zero = DAG.getConstantFP(0.0, SL, VT);3163  SDValue Underflow =3164      DAG.getSetCC(SL, SetCCVT, X, UnderflowCheckConst, ISD::SETOLT);3165 3166  R = DAG.getNode(ISD::SELECT, SL, VT, Underflow, Zero, R);3167 3168  if (!Flags.hasNoInfs()) {3169    SDValue OverflowCheckConst =3170        DAG.getConstantFP(IsExp10 ? 0x1.344136p+5f : 0x1.62e430p+6f, SL, VT);3171    SDValue Overflow =3172        DAG.getSetCC(SL, SetCCVT, X, OverflowCheckConst, ISD::SETOGT);3173    SDValue Inf =3174        DAG.getConstantFP(APFloat::getInf(APFloat::IEEEsingle()), SL, VT);3175    R = DAG.getNode(ISD::SELECT, SL, VT, Overflow, Inf, R);3176  }3177 3178  return R;3179}3180 3181static bool isCtlzOpc(unsigned Opc) {3182  return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_UNDEF;3183}3184 3185static bool isCttzOpc(unsigned Opc) {3186  return Opc == ISD::CTTZ || Opc == ISD::CTTZ_ZERO_UNDEF;3187}3188 3189SDValue AMDGPUTargetLowering::lowerCTLZResults(SDValue Op,3190                                               SelectionDAG &DAG) const {3191  auto SL = SDLoc(Op);3192  auto Opc = Op.getOpcode();3193  auto Arg = Op.getOperand(0u);3194  auto ResultVT = Op.getValueType();3195 3196  if (ResultVT != MVT::i8 && ResultVT != MVT::i16)3197    return {};3198 3199  assert(isCtlzOpc(Opc));3200  assert(ResultVT == Arg.getValueType());3201 3202  const uint64_t NumBits = ResultVT.getFixedSizeInBits();3203  SDValue NumExtBits = DAG.getConstant(32u - NumBits, SL, MVT::i32);3204  SDValue NewOp;3205 3206  if (Opc == ISD::CTLZ_ZERO_UNDEF) {3207    NewOp = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Arg);3208    NewOp = DAG.getNode(ISD::SHL, SL, MVT::i32, NewOp, NumExtBits);3209    NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);3210  } else {3211    NewOp = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Arg);3212    NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp);3213    NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, NumExtBits);3214  }3215 3216  return DAG.getNode(ISD::TRUNCATE, SL, ResultVT, NewOp);3217}3218 3219SDValue AMDGPUTargetLowering::LowerCTLZ_CTTZ(SDValue Op, SelectionDAG &DAG) const {3220  SDLoc SL(Op);3221  SDValue Src = Op.getOperand(0);3222 3223  assert(isCtlzOpc(Op.getOpcode()) || isCttzOpc(Op.getOpcode()));3224  bool Ctlz = isCtlzOpc(Op.getOpcode());3225  unsigned NewOpc = Ctlz ? AMDGPUISD::FFBH_U32 : AMDGPUISD::FFBL_B32;3226 3227  bool ZeroUndef = Op.getOpcode() == ISD::CTLZ_ZERO_UNDEF ||3228                   Op.getOpcode() == ISD::CTTZ_ZERO_UNDEF;3229  bool Is64BitScalar = !Src->isDivergent() && Src.getValueType() == MVT::i64;3230 3231  if (Src.getValueType() == MVT::i32 || Is64BitScalar) {3232    // (ctlz hi:lo) -> (umin (ffbh src), 32)3233    // (cttz hi:lo) -> (umin (ffbl src), 32)3234    // (ctlz_zero_undef src) -> (ffbh src)3235    // (cttz_zero_undef src) -> (ffbl src)3236 3237    //  64-bit scalar version produce 32-bit result3238    // (ctlz hi:lo) -> (umin (S_FLBIT_I32_B64 src), 64)3239    // (cttz hi:lo) -> (umin (S_FF1_I32_B64 src), 64)3240    // (ctlz_zero_undef src) -> (S_FLBIT_I32_B64 src)3241    // (cttz_zero_undef src) -> (S_FF1_I32_B64 src)3242    SDValue NewOpr = DAG.getNode(NewOpc, SL, MVT::i32, Src);3243    if (!ZeroUndef) {3244      const SDValue ConstVal = DAG.getConstant(3245          Op.getValueType().getScalarSizeInBits(), SL, MVT::i32);3246      NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, ConstVal);3247    }3248    return DAG.getNode(ISD::ZERO_EXTEND, SL, Src.getValueType(), NewOpr);3249  }3250 3251  SDValue Lo, Hi;3252  std::tie(Lo, Hi) = split64BitValue(Src, DAG);3253 3254  SDValue OprLo = DAG.getNode(NewOpc, SL, MVT::i32, Lo);3255  SDValue OprHi = DAG.getNode(NewOpc, SL, MVT::i32, Hi);3256 3257  // (ctlz hi:lo) -> (umin3 (ffbh hi), (uaddsat (ffbh lo), 32), 64)3258  // (cttz hi:lo) -> (umin3 (uaddsat (ffbl hi), 32), (ffbl lo), 64)3259  // (ctlz_zero_undef hi:lo) -> (umin (ffbh hi), (add (ffbh lo), 32))3260  // (cttz_zero_undef hi:lo) -> (umin (add (ffbl hi), 32), (ffbl lo))3261 3262  unsigned AddOpc = ZeroUndef ? ISD::ADD : ISD::UADDSAT;3263  const SDValue Const32 = DAG.getConstant(32, SL, MVT::i32);3264  if (Ctlz)3265    OprLo = DAG.getNode(AddOpc, SL, MVT::i32, OprLo, Const32);3266  else3267    OprHi = DAG.getNode(AddOpc, SL, MVT::i32, OprHi, Const32);3268 3269  SDValue NewOpr;3270  NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, OprLo, OprHi);3271  if (!ZeroUndef) {3272    const SDValue Const64 = DAG.getConstant(64, SL, MVT::i32);3273    NewOpr = DAG.getNode(ISD::UMIN, SL, MVT::i32, NewOpr, Const64);3274  }3275 3276  return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, NewOpr);3277}3278 3279SDValue AMDGPUTargetLowering::LowerINT_TO_FP32(SDValue Op, SelectionDAG &DAG,3280                                               bool Signed) const {3281  // The regular method converting a 64-bit integer to float roughly consists of3282  // 2 steps: normalization and rounding. In fact, after normalization, the3283  // conversion from a 64-bit integer to a float is essentially the same as the3284  // one from a 32-bit integer. The only difference is that it has more3285  // trailing bits to be rounded. To leverage the native 32-bit conversion, a3286  // 64-bit integer could be preprocessed and fit into a 32-bit integer then3287  // converted into the correct float number. The basic steps for the unsigned3288  // conversion are illustrated in the following pseudo code:3289  //3290  // f32 uitofp(i64 u) {3291  //   i32 hi, lo = split(u);3292  //   // Only count the leading zeros in hi as we have native support of the3293  //   // conversion from i32 to f32. If hi is all 0s, the conversion is3294  //   // reduced to a 32-bit one automatically.3295  //   i32 shamt = clz(hi); // Return 32 if hi is all 0s.3296  //   u <<= shamt;3297  //   hi, lo = split(u);3298  //   hi |= (lo != 0) ? 1 : 0; // Adjust rounding bit in hi based on lo.3299  //   // convert it as a 32-bit integer and scale the result back.3300  //   return uitofp(hi) * 2^(32 - shamt);3301  // }3302  //3303  // The signed one follows the same principle but uses 'ffbh_i32' to count its3304  // sign bits instead. If 'ffbh_i32' is not available, its absolute value is3305  // converted instead followed by negation based its sign bit.3306 3307  SDLoc SL(Op);3308  SDValue Src = Op.getOperand(0);3309 3310  SDValue Lo, Hi;3311  std::tie(Lo, Hi) = split64BitValue(Src, DAG);3312  SDValue Sign;3313  SDValue ShAmt;3314  if (Signed && Subtarget->isGCN()) {3315    // We also need to consider the sign bit in Lo if Hi has just sign bits,3316    // i.e. Hi is 0 or -1. However, that only needs to take the MSB into3317    // account. That is, the maximal shift is3318    // - 32 if Lo and Hi have opposite signs;3319    // - 33 if Lo and Hi have the same sign.3320    //3321    // Or, MaxShAmt = 33 + OppositeSign, where3322    //3323    // OppositeSign is defined as ((Lo ^ Hi) >> 31), which is3324    // - -1 if Lo and Hi have opposite signs; and3325    // -  0 otherwise.3326    //3327    // All in all, ShAmt is calculated as3328    //3329    //  umin(sffbh(Hi), 33 + (Lo^Hi)>>31) - 1.3330    //3331    // or3332    //3333    //  umin(sffbh(Hi) - 1, 32 + (Lo^Hi)>>31).3334    //3335    // to reduce the critical path.3336    SDValue OppositeSign = DAG.getNode(3337        ISD::SRA, SL, MVT::i32, DAG.getNode(ISD::XOR, SL, MVT::i32, Lo, Hi),3338        DAG.getConstant(31, SL, MVT::i32));3339    SDValue MaxShAmt =3340        DAG.getNode(ISD::ADD, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),3341                    OppositeSign);3342    // Count the leading sign bits.3343    ShAmt = DAG.getNode(AMDGPUISD::FFBH_I32, SL, MVT::i32, Hi);3344    // Different from unsigned conversion, the shift should be one bit less to3345    // preserve the sign bit.3346    ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, ShAmt,3347                        DAG.getConstant(1, SL, MVT::i32));3348    ShAmt = DAG.getNode(ISD::UMIN, SL, MVT::i32, ShAmt, MaxShAmt);3349  } else {3350    if (Signed) {3351      // Without 'ffbh_i32', only leading zeros could be counted. Take the3352      // absolute value first.3353      Sign = DAG.getNode(ISD::SRA, SL, MVT::i64, Src,3354                         DAG.getConstant(63, SL, MVT::i64));3355      SDValue Abs =3356          DAG.getNode(ISD::XOR, SL, MVT::i64,3357                      DAG.getNode(ISD::ADD, SL, MVT::i64, Src, Sign), Sign);3358      std::tie(Lo, Hi) = split64BitValue(Abs, DAG);3359    }3360    // Count the leading zeros.3361    ShAmt = DAG.getNode(ISD::CTLZ, SL, MVT::i32, Hi);3362    // The shift amount for signed integers is [0, 32].3363  }3364  // Normalize the given 64-bit integer.3365  SDValue Norm = DAG.getNode(ISD::SHL, SL, MVT::i64, Src, ShAmt);3366  // Split it again.3367  std::tie(Lo, Hi) = split64BitValue(Norm, DAG);3368  // Calculate the adjust bit for rounding.3369  // (lo != 0) ? 1 : 0 => (lo >= 1) ? 1 : 0 => umin(1, lo)3370  SDValue Adjust = DAG.getNode(ISD::UMIN, SL, MVT::i32,3371                               DAG.getConstant(1, SL, MVT::i32), Lo);3372  // Get the 32-bit normalized integer.3373  Norm = DAG.getNode(ISD::OR, SL, MVT::i32, Hi, Adjust);3374  // Convert the normalized 32-bit integer into f32.3375  unsigned Opc =3376      (Signed && Subtarget->isGCN()) ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;3377  SDValue FVal = DAG.getNode(Opc, SL, MVT::f32, Norm);3378 3379  // Finally, need to scale back the converted floating number as the original3380  // 64-bit integer is converted as a 32-bit one.3381  ShAmt = DAG.getNode(ISD::SUB, SL, MVT::i32, DAG.getConstant(32, SL, MVT::i32),3382                      ShAmt);3383  // On GCN, use LDEXP directly.3384  if (Subtarget->isGCN())3385    return DAG.getNode(ISD::FLDEXP, SL, MVT::f32, FVal, ShAmt);3386 3387  // Otherwise, align 'ShAmt' to the exponent part and add it into the exponent3388  // part directly to emulate the multiplication of 2^ShAmt. That 8-bit3389  // exponent is enough to avoid overflowing into the sign bit.3390  SDValue Exp = DAG.getNode(ISD::SHL, SL, MVT::i32, ShAmt,3391                            DAG.getConstant(23, SL, MVT::i32));3392  SDValue IVal =3393      DAG.getNode(ISD::ADD, SL, MVT::i32,3394                  DAG.getNode(ISD::BITCAST, SL, MVT::i32, FVal), Exp);3395  if (Signed) {3396    // Set the sign bit.3397    Sign = DAG.getNode(ISD::SHL, SL, MVT::i32,3398                       DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Sign),3399                       DAG.getConstant(31, SL, MVT::i32));3400    IVal = DAG.getNode(ISD::OR, SL, MVT::i32, IVal, Sign);3401  }3402  return DAG.getNode(ISD::BITCAST, SL, MVT::f32, IVal);3403}3404 3405SDValue AMDGPUTargetLowering::LowerINT_TO_FP64(SDValue Op, SelectionDAG &DAG,3406                                               bool Signed) const {3407  SDLoc SL(Op);3408  SDValue Src = Op.getOperand(0);3409 3410  SDValue Lo, Hi;3411  std::tie(Lo, Hi) = split64BitValue(Src, DAG);3412 3413  SDValue CvtHi = DAG.getNode(Signed ? ISD::SINT_TO_FP : ISD::UINT_TO_FP,3414                              SL, MVT::f64, Hi);3415 3416  SDValue CvtLo = DAG.getNode(ISD::UINT_TO_FP, SL, MVT::f64, Lo);3417 3418  SDValue LdExp = DAG.getNode(ISD::FLDEXP, SL, MVT::f64, CvtHi,3419                              DAG.getConstant(32, SL, MVT::i32));3420  // TODO: Should this propagate fast-math-flags?3421  return DAG.getNode(ISD::FADD, SL, MVT::f64, LdExp, CvtLo);3422}3423 3424SDValue AMDGPUTargetLowering::LowerUINT_TO_FP(SDValue Op,3425                                               SelectionDAG &DAG) const {3426  // TODO: Factor out code common with LowerSINT_TO_FP.3427  EVT DestVT = Op.getValueType();3428  SDValue Src = Op.getOperand(0);3429  EVT SrcVT = Src.getValueType();3430 3431  if (SrcVT == MVT::i16) {3432    if (DestVT == MVT::f16)3433      return Op;3434    SDLoc DL(Op);3435 3436    // Promote src to i323437    SDValue Ext = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Src);3438    return DAG.getNode(ISD::UINT_TO_FP, DL, DestVT, Ext);3439  }3440 3441  if (DestVT == MVT::bf16) {3442    SDLoc SL(Op);3443    SDValue ToF32 = DAG.getNode(ISD::UINT_TO_FP, SL, MVT::f32, Src);3444    SDValue FPRoundFlag = DAG.getIntPtrConstant(0, SL, /*isTarget=*/true);3445    return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ToF32, FPRoundFlag);3446  }3447 3448  if (SrcVT != MVT::i64)3449    return Op;3450 3451  if (Subtarget->has16BitInsts() && DestVT == MVT::f16) {3452    SDLoc DL(Op);3453 3454    SDValue IntToFp32 = DAG.getNode(Op.getOpcode(), DL, MVT::f32, Src);3455    SDValue FPRoundFlag =3456        DAG.getIntPtrConstant(0, SDLoc(Op), /*isTarget=*/true);3457    SDValue FPRound =3458        DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, IntToFp32, FPRoundFlag);3459 3460    return FPRound;3461  }3462 3463  if (DestVT == MVT::f32)3464    return LowerINT_TO_FP32(Op, DAG, false);3465 3466  assert(DestVT == MVT::f64);3467  return LowerINT_TO_FP64(Op, DAG, false);3468}3469 3470SDValue AMDGPUTargetLowering::LowerSINT_TO_FP(SDValue Op,3471                                              SelectionDAG &DAG) const {3472  EVT DestVT = Op.getValueType();3473 3474  SDValue Src = Op.getOperand(0);3475  EVT SrcVT = Src.getValueType();3476 3477  if (SrcVT == MVT::i16) {3478    if (DestVT == MVT::f16)3479      return Op;3480 3481    SDLoc DL(Op);3482    // Promote src to i323483    SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i32, Src);3484    return DAG.getNode(ISD::SINT_TO_FP, DL, DestVT, Ext);3485  }3486 3487  if (DestVT == MVT::bf16) {3488    SDLoc SL(Op);3489    SDValue ToF32 = DAG.getNode(ISD::SINT_TO_FP, SL, MVT::f32, Src);3490    SDValue FPRoundFlag = DAG.getIntPtrConstant(0, SL, /*isTarget=*/true);3491    return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ToF32, FPRoundFlag);3492  }3493 3494  if (SrcVT != MVT::i64)3495    return Op;3496 3497  // TODO: Factor out code common with LowerUINT_TO_FP.3498 3499  if (Subtarget->has16BitInsts() && DestVT == MVT::f16) {3500    SDLoc DL(Op);3501    SDValue Src = Op.getOperand(0);3502 3503    SDValue IntToFp32 = DAG.getNode(Op.getOpcode(), DL, MVT::f32, Src);3504    SDValue FPRoundFlag =3505        DAG.getIntPtrConstant(0, SDLoc(Op), /*isTarget=*/true);3506    SDValue FPRound =3507        DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, IntToFp32, FPRoundFlag);3508 3509    return FPRound;3510  }3511 3512  if (DestVT == MVT::f32)3513    return LowerINT_TO_FP32(Op, DAG, true);3514 3515  assert(DestVT == MVT::f64);3516  return LowerINT_TO_FP64(Op, DAG, true);3517}3518 3519SDValue AMDGPUTargetLowering::LowerFP_TO_INT64(SDValue Op, SelectionDAG &DAG,3520                                               bool Signed) const {3521  SDLoc SL(Op);3522 3523  SDValue Src = Op.getOperand(0);3524  EVT SrcVT = Src.getValueType();3525 3526  assert(SrcVT == MVT::f32 || SrcVT == MVT::f64);3527 3528  // The basic idea of converting a floating point number into a pair of 32-bit3529  // integers is illustrated as follows:3530  //3531  //     tf := trunc(val);3532  //    hif := floor(tf * 2^-32);3533  //    lof := tf - hif * 2^32; // lof is always positive due to floor.3534  //     hi := fptoi(hif);3535  //     lo := fptoi(lof);3536  //3537  SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, SrcVT, Src);3538  SDValue Sign;3539  if (Signed && SrcVT == MVT::f32) {3540    // However, a 32-bit floating point number has only 23 bits mantissa and3541    // it's not enough to hold all the significant bits of `lof` if val is3542    // negative. To avoid the loss of precision, We need to take the absolute3543    // value after truncating and flip the result back based on the original3544    // signedness.3545    Sign = DAG.getNode(ISD::SRA, SL, MVT::i32,3546                       DAG.getNode(ISD::BITCAST, SL, MVT::i32, Trunc),3547                       DAG.getConstant(31, SL, MVT::i32));3548    Trunc = DAG.getNode(ISD::FABS, SL, SrcVT, Trunc);3549  }3550 3551  SDValue K0, K1;3552  if (SrcVT == MVT::f64) {3553    K0 = DAG.getConstantFP(3554        llvm::bit_cast<double>(UINT64_C(/*2^-32*/ 0x3df0000000000000)), SL,3555        SrcVT);3556    K1 = DAG.getConstantFP(3557        llvm::bit_cast<double>(UINT64_C(/*-2^32*/ 0xc1f0000000000000)), SL,3558        SrcVT);3559  } else {3560    K0 = DAG.getConstantFP(3561        llvm::bit_cast<float>(UINT32_C(/*2^-32*/ 0x2f800000)), SL, SrcVT);3562    K1 = DAG.getConstantFP(3563        llvm::bit_cast<float>(UINT32_C(/*-2^32*/ 0xcf800000)), SL, SrcVT);3564  }3565  // TODO: Should this propagate fast-math-flags?3566  SDValue Mul = DAG.getNode(ISD::FMUL, SL, SrcVT, Trunc, K0);3567 3568  SDValue FloorMul = DAG.getNode(ISD::FFLOOR, SL, SrcVT, Mul);3569 3570  SDValue Fma = DAG.getNode(ISD::FMA, SL, SrcVT, FloorMul, K1, Trunc);3571 3572  SDValue Hi = DAG.getNode((Signed && SrcVT == MVT::f64) ? ISD::FP_TO_SINT3573                                                         : ISD::FP_TO_UINT,3574                           SL, MVT::i32, FloorMul);3575  SDValue Lo = DAG.getNode(ISD::FP_TO_UINT, SL, MVT::i32, Fma);3576 3577  SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64,3578                               DAG.getBuildVector(MVT::v2i32, SL, {Lo, Hi}));3579 3580  if (Signed && SrcVT == MVT::f32) {3581    assert(Sign);3582    // Flip the result based on the signedness, which is either all 0s or 1s.3583    Sign = DAG.getNode(ISD::BITCAST, SL, MVT::i64,3584                       DAG.getBuildVector(MVT::v2i32, SL, {Sign, Sign}));3585    // r := xor(r, sign) - sign;3586    Result =3587        DAG.getNode(ISD::SUB, SL, MVT::i64,3588                    DAG.getNode(ISD::XOR, SL, MVT::i64, Result, Sign), Sign);3589  }3590 3591  return Result;3592}3593 3594SDValue AMDGPUTargetLowering::LowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const {3595  SDLoc DL(Op);3596  SDValue N0 = Op.getOperand(0);3597 3598  // Convert to target node to get known bits3599  if (N0.getValueType() == MVT::f32)3600    return DAG.getNode(AMDGPUISD::FP_TO_FP16, DL, Op.getValueType(), N0);3601 3602  if (Op->getFlags().hasApproximateFuncs()) {3603    // There is a generic expand for FP_TO_FP16 with unsafe fast math.3604    return SDValue();3605  }3606 3607  return LowerF64ToF16Safe(N0, DL, DAG);3608}3609 3610// return node in i323611SDValue AMDGPUTargetLowering::LowerF64ToF16Safe(SDValue Src, const SDLoc &DL,3612                                                SelectionDAG &DAG) const {3613  assert(Src.getSimpleValueType() == MVT::f64);3614 3615  // f64 -> f16 conversion using round-to-nearest-even rounding mode.3616  // TODO: We can generate better code for True16.3617  const unsigned ExpMask = 0x7ff;3618  const unsigned ExpBiasf64 = 1023;3619  const unsigned ExpBiasf16 = 15;3620  SDValue Zero = DAG.getConstant(0, DL, MVT::i32);3621  SDValue One = DAG.getConstant(1, DL, MVT::i32);3622  SDValue U = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Src);3623  SDValue UH = DAG.getNode(ISD::SRL, DL, MVT::i64, U,3624                           DAG.getConstant(32, DL, MVT::i64));3625  UH = DAG.getZExtOrTrunc(UH, DL, MVT::i32);3626  U = DAG.getZExtOrTrunc(U, DL, MVT::i32);3627  SDValue E = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,3628                          DAG.getConstant(20, DL, MVT::i64));3629  E = DAG.getNode(ISD::AND, DL, MVT::i32, E,3630                  DAG.getConstant(ExpMask, DL, MVT::i32));3631  // Subtract the fp64 exponent bias (1023) to get the real exponent and3632  // add the f16 bias (15) to get the biased exponent for the f16 format.3633  E = DAG.getNode(ISD::ADD, DL, MVT::i32, E,3634                  DAG.getConstant(-ExpBiasf64 + ExpBiasf16, DL, MVT::i32));3635 3636  SDValue M = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,3637                          DAG.getConstant(8, DL, MVT::i32));3638  M = DAG.getNode(ISD::AND, DL, MVT::i32, M,3639                  DAG.getConstant(0xffe, DL, MVT::i32));3640 3641  SDValue MaskedSig = DAG.getNode(ISD::AND, DL, MVT::i32, UH,3642                                  DAG.getConstant(0x1ff, DL, MVT::i32));3643  MaskedSig = DAG.getNode(ISD::OR, DL, MVT::i32, MaskedSig, U);3644 3645  SDValue Lo40Set = DAG.getSelectCC(DL, MaskedSig, Zero, Zero, One, ISD::SETEQ);3646  M = DAG.getNode(ISD::OR, DL, MVT::i32, M, Lo40Set);3647 3648  // (M != 0 ? 0x0200 : 0) | 0x7c00;3649  SDValue I = DAG.getNode(ISD::OR, DL, MVT::i32,3650      DAG.getSelectCC(DL, M, Zero, DAG.getConstant(0x0200, DL, MVT::i32),3651                      Zero, ISD::SETNE), DAG.getConstant(0x7c00, DL, MVT::i32));3652 3653  // N = M | (E << 12);3654  SDValue N = DAG.getNode(ISD::OR, DL, MVT::i32, M,3655      DAG.getNode(ISD::SHL, DL, MVT::i32, E,3656                  DAG.getConstant(12, DL, MVT::i32)));3657 3658  // B = clamp(1-E, 0, 13);3659  SDValue OneSubExp = DAG.getNode(ISD::SUB, DL, MVT::i32,3660                                  One, E);3661  SDValue B = DAG.getNode(ISD::SMAX, DL, MVT::i32, OneSubExp, Zero);3662  B = DAG.getNode(ISD::SMIN, DL, MVT::i32, B,3663                  DAG.getConstant(13, DL, MVT::i32));3664 3665  SDValue SigSetHigh = DAG.getNode(ISD::OR, DL, MVT::i32, M,3666                                   DAG.getConstant(0x1000, DL, MVT::i32));3667 3668  SDValue D = DAG.getNode(ISD::SRL, DL, MVT::i32, SigSetHigh, B);3669  SDValue D0 = DAG.getNode(ISD::SHL, DL, MVT::i32, D, B);3670  SDValue D1 = DAG.getSelectCC(DL, D0, SigSetHigh, One, Zero, ISD::SETNE);3671  D = DAG.getNode(ISD::OR, DL, MVT::i32, D, D1);3672 3673  SDValue V = DAG.getSelectCC(DL, E, One, D, N, ISD::SETLT);3674  SDValue VLow3 = DAG.getNode(ISD::AND, DL, MVT::i32, V,3675                              DAG.getConstant(0x7, DL, MVT::i32));3676  V = DAG.getNode(ISD::SRL, DL, MVT::i32, V,3677                  DAG.getConstant(2, DL, MVT::i32));3678  SDValue V0 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(3, DL, MVT::i32),3679                               One, Zero, ISD::SETEQ);3680  SDValue V1 = DAG.getSelectCC(DL, VLow3, DAG.getConstant(5, DL, MVT::i32),3681                               One, Zero, ISD::SETGT);3682  V1 = DAG.getNode(ISD::OR, DL, MVT::i32, V0, V1);3683  V = DAG.getNode(ISD::ADD, DL, MVT::i32, V, V1);3684 3685  V = DAG.getSelectCC(DL, E, DAG.getConstant(30, DL, MVT::i32),3686                      DAG.getConstant(0x7c00, DL, MVT::i32), V, ISD::SETGT);3687  V = DAG.getSelectCC(DL, E, DAG.getConstant(1039, DL, MVT::i32),3688                      I, V, ISD::SETEQ);3689 3690  // Extract the sign bit.3691  SDValue Sign = DAG.getNode(ISD::SRL, DL, MVT::i32, UH,3692                            DAG.getConstant(16, DL, MVT::i32));3693  Sign = DAG.getNode(ISD::AND, DL, MVT::i32, Sign,3694                     DAG.getConstant(0x8000, DL, MVT::i32));3695 3696  return DAG.getNode(ISD::OR, DL, MVT::i32, Sign, V);3697}3698 3699SDValue AMDGPUTargetLowering::LowerFP_TO_INT(const SDValue Op,3700                                             SelectionDAG &DAG) const {3701  SDValue Src = Op.getOperand(0);3702  unsigned OpOpcode = Op.getOpcode();3703  EVT SrcVT = Src.getValueType();3704  EVT DestVT = Op.getValueType();3705 3706  // Will be selected natively3707  if (SrcVT == MVT::f16 && DestVT == MVT::i16)3708    return Op;3709 3710  if (SrcVT == MVT::bf16) {3711    SDLoc DL(Op);3712    SDValue PromotedSrc = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);3713    return DAG.getNode(Op.getOpcode(), DL, DestVT, PromotedSrc);3714  }3715 3716  // Promote i16 to i323717  if (DestVT == MVT::i16 && (SrcVT == MVT::f32 || SrcVT == MVT::f64)) {3718    SDLoc DL(Op);3719 3720    SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);3721    return DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToInt32);3722  }3723 3724  if (DestVT != MVT::i64)3725    return Op;3726 3727  if (SrcVT == MVT::f16 ||3728      (SrcVT == MVT::f32 && Src.getOpcode() == ISD::FP16_TO_FP)) {3729    SDLoc DL(Op);3730 3731    SDValue FpToInt32 = DAG.getNode(OpOpcode, DL, MVT::i32, Src);3732    unsigned Ext =3733        OpOpcode == ISD::FP_TO_SINT ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;3734    return DAG.getNode(Ext, DL, MVT::i64, FpToInt32);3735  }3736 3737  if (SrcVT == MVT::f32 || SrcVT == MVT::f64)3738    return LowerFP_TO_INT64(Op, DAG, OpOpcode == ISD::FP_TO_SINT);3739 3740  return SDValue();3741}3742 3743SDValue AMDGPUTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,3744                                                     SelectionDAG &DAG) const {3745  EVT ExtraVT = cast<VTSDNode>(Op.getOperand(1))->getVT();3746  MVT VT = Op.getSimpleValueType();3747  MVT ScalarVT = VT.getScalarType();3748 3749  assert(VT.isVector());3750 3751  SDValue Src = Op.getOperand(0);3752  SDLoc DL(Op);3753 3754  // TODO: Don't scalarize on Evergreen?3755  unsigned NElts = VT.getVectorNumElements();3756  SmallVector<SDValue, 8> Args;3757  DAG.ExtractVectorElements(Src, Args, 0, NElts);3758 3759  SDValue VTOp = DAG.getValueType(ExtraVT.getScalarType());3760  for (unsigned I = 0; I < NElts; ++I)3761    Args[I] = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, ScalarVT, Args[I], VTOp);3762 3763  return DAG.getBuildVector(VT, DL, Args);3764}3765 3766//===----------------------------------------------------------------------===//3767// Custom DAG optimizations3768//===----------------------------------------------------------------------===//3769 3770static bool isU24(SDValue Op, SelectionDAG &DAG) {3771  return AMDGPUTargetLowering::numBitsUnsigned(Op, DAG) <= 24;3772}3773 3774static bool isI24(SDValue Op, SelectionDAG &DAG) {3775  EVT VT = Op.getValueType();3776  return VT.getSizeInBits() >= 24 && // Types less than 24-bit should be treated3777                                     // as unsigned 24-bit values.3778         AMDGPUTargetLowering::numBitsSigned(Op, DAG) <= 24;3779}3780 3781static SDValue simplifyMul24(SDNode *Node24,3782                             TargetLowering::DAGCombinerInfo &DCI) {3783  SelectionDAG &DAG = DCI.DAG;3784  const TargetLowering &TLI = DAG.getTargetLoweringInfo();3785  bool IsIntrin = Node24->getOpcode() == ISD::INTRINSIC_WO_CHAIN;3786 3787  SDValue LHS = IsIntrin ? Node24->getOperand(1) : Node24->getOperand(0);3788  SDValue RHS = IsIntrin ? Node24->getOperand(2) : Node24->getOperand(1);3789  unsigned NewOpcode = Node24->getOpcode();3790  if (IsIntrin) {3791    unsigned IID = Node24->getConstantOperandVal(0);3792    switch (IID) {3793    case Intrinsic::amdgcn_mul_i24:3794      NewOpcode = AMDGPUISD::MUL_I24;3795      break;3796    case Intrinsic::amdgcn_mul_u24:3797      NewOpcode = AMDGPUISD::MUL_U24;3798      break;3799    case Intrinsic::amdgcn_mulhi_i24:3800      NewOpcode = AMDGPUISD::MULHI_I24;3801      break;3802    case Intrinsic::amdgcn_mulhi_u24:3803      NewOpcode = AMDGPUISD::MULHI_U24;3804      break;3805    default:3806      llvm_unreachable("Expected 24-bit mul intrinsic");3807    }3808  }3809 3810  APInt Demanded = APInt::getLowBitsSet(LHS.getValueSizeInBits(), 24);3811 3812  // First try to simplify using SimplifyMultipleUseDemandedBits which allows3813  // the operands to have other uses, but will only perform simplifications that3814  // involve bypassing some nodes for this user.3815  SDValue DemandedLHS = TLI.SimplifyMultipleUseDemandedBits(LHS, Demanded, DAG);3816  SDValue DemandedRHS = TLI.SimplifyMultipleUseDemandedBits(RHS, Demanded, DAG);3817  if (DemandedLHS || DemandedRHS)3818    return DAG.getNode(NewOpcode, SDLoc(Node24), Node24->getVTList(),3819                       DemandedLHS ? DemandedLHS : LHS,3820                       DemandedRHS ? DemandedRHS : RHS);3821 3822  // Now try SimplifyDemandedBits which can simplify the nodes used by our3823  // operands if this node is the only user.3824  if (TLI.SimplifyDemandedBits(LHS, Demanded, DCI))3825    return SDValue(Node24, 0);3826  if (TLI.SimplifyDemandedBits(RHS, Demanded, DCI))3827    return SDValue(Node24, 0);3828 3829  return SDValue();3830}3831 3832template <typename IntTy>3833static SDValue constantFoldBFE(SelectionDAG &DAG, IntTy Src0, uint32_t Offset,3834                               uint32_t Width, const SDLoc &DL) {3835  if (Width + Offset < 32) {3836    uint32_t Shl = static_cast<uint32_t>(Src0) << (32 - Offset - Width);3837    IntTy Result = static_cast<IntTy>(Shl) >> (32 - Width);3838    if constexpr (std::is_signed_v<IntTy>) {3839      return DAG.getSignedConstant(Result, DL, MVT::i32);3840    } else {3841      return DAG.getConstant(Result, DL, MVT::i32);3842    }3843  }3844 3845  return DAG.getConstant(Src0 >> Offset, DL, MVT::i32);3846}3847 3848static bool hasVolatileUser(SDNode *Val) {3849  for (SDNode *U : Val->users()) {3850    if (MemSDNode *M = dyn_cast<MemSDNode>(U)) {3851      if (M->isVolatile())3852        return true;3853    }3854  }3855 3856  return false;3857}3858 3859bool AMDGPUTargetLowering::shouldCombineMemoryType(EVT VT) const {3860  // i32 vectors are the canonical memory type.3861  if (VT.getScalarType() == MVT::i32 || isTypeLegal(VT))3862    return false;3863 3864  if (!VT.isByteSized())3865    return false;3866 3867  unsigned Size = VT.getStoreSize();3868 3869  if ((Size == 1 || Size == 2 || Size == 4) && !VT.isVector())3870    return false;3871 3872  if (Size == 3 || (Size > 4 && (Size % 4 != 0)))3873    return false;3874 3875  return true;3876}3877 3878// Replace load of an illegal type with a bitcast from a load of a friendlier3879// type.3880SDValue AMDGPUTargetLowering::performLoadCombine(SDNode *N,3881                                                 DAGCombinerInfo &DCI) const {3882  if (!DCI.isBeforeLegalize())3883    return SDValue();3884 3885  LoadSDNode *LN = cast<LoadSDNode>(N);3886  if (!LN->isSimple() || !ISD::isNormalLoad(LN) || hasVolatileUser(LN))3887    return SDValue();3888 3889  SDLoc SL(N);3890  SelectionDAG &DAG = DCI.DAG;3891  EVT VT = LN->getMemoryVT();3892 3893  unsigned Size = VT.getStoreSize();3894  Align Alignment = LN->getAlign();3895  if (Alignment < Size && isTypeLegal(VT)) {3896    unsigned IsFast;3897    unsigned AS = LN->getAddressSpace();3898 3899    // Expand unaligned loads earlier than legalization. Due to visitation order3900    // problems during legalization, the emitted instructions to pack and unpack3901    // the bytes again are not eliminated in the case of an unaligned copy.3902    if (!allowsMisalignedMemoryAccesses(3903            VT, AS, Alignment, LN->getMemOperand()->getFlags(), &IsFast)) {3904      if (VT.isVector())3905        return SplitVectorLoad(SDValue(LN, 0), DAG);3906 3907      SDValue Ops[2];3908      std::tie(Ops[0], Ops[1]) = expandUnalignedLoad(LN, DAG);3909 3910      return DAG.getMergeValues(Ops, SDLoc(N));3911    }3912 3913    if (!IsFast)3914      return SDValue();3915  }3916 3917  if (!shouldCombineMemoryType(VT))3918    return SDValue();3919 3920  EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);3921 3922  SDValue NewLoad3923    = DAG.getLoad(NewVT, SL, LN->getChain(),3924                  LN->getBasePtr(), LN->getMemOperand());3925 3926  SDValue BC = DAG.getNode(ISD::BITCAST, SL, VT, NewLoad);3927  DCI.CombineTo(N, BC, NewLoad.getValue(1));3928  return SDValue(N, 0);3929}3930 3931// Replace store of an illegal type with a store of a bitcast to a friendlier3932// type.3933SDValue AMDGPUTargetLowering::performStoreCombine(SDNode *N,3934                                                  DAGCombinerInfo &DCI) const {3935  if (!DCI.isBeforeLegalize())3936    return SDValue();3937 3938  StoreSDNode *SN = cast<StoreSDNode>(N);3939  if (!SN->isSimple() || !ISD::isNormalStore(SN))3940    return SDValue();3941 3942  EVT VT = SN->getMemoryVT();3943  unsigned Size = VT.getStoreSize();3944 3945  SDLoc SL(N);3946  SelectionDAG &DAG = DCI.DAG;3947  Align Alignment = SN->getAlign();3948  if (Alignment < Size && isTypeLegal(VT)) {3949    unsigned IsFast;3950    unsigned AS = SN->getAddressSpace();3951 3952    // Expand unaligned stores earlier than legalization. Due to visitation3953    // order problems during legalization, the emitted instructions to pack and3954    // unpack the bytes again are not eliminated in the case of an unaligned3955    // copy.3956    if (!allowsMisalignedMemoryAccesses(3957            VT, AS, Alignment, SN->getMemOperand()->getFlags(), &IsFast)) {3958      if (VT.isVector())3959        return SplitVectorStore(SDValue(SN, 0), DAG);3960 3961      return expandUnalignedStore(SN, DAG);3962    }3963 3964    if (!IsFast)3965      return SDValue();3966  }3967 3968  if (!shouldCombineMemoryType(VT))3969    return SDValue();3970 3971  EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);3972  SDValue Val = SN->getValue();3973 3974  //DCI.AddToWorklist(Val.getNode());3975 3976  bool OtherUses = !Val.hasOneUse();3977  SDValue CastVal = DAG.getNode(ISD::BITCAST, SL, NewVT, Val);3978  if (OtherUses) {3979    SDValue CastBack = DAG.getNode(ISD::BITCAST, SL, VT, CastVal);3980    DAG.ReplaceAllUsesOfValueWith(Val, CastBack);3981  }3982 3983  return DAG.getStore(SN->getChain(), SL, CastVal,3984                      SN->getBasePtr(), SN->getMemOperand());3985}3986 3987// FIXME: This should go in generic DAG combiner with an isTruncateFree check,3988// but isTruncateFree is inaccurate for i16 now because of SALU vs. VALU3989// issues.3990SDValue AMDGPUTargetLowering::performAssertSZExtCombine(SDNode *N,3991                                                        DAGCombinerInfo &DCI) const {3992  SelectionDAG &DAG = DCI.DAG;3993  SDValue N0 = N->getOperand(0);3994 3995  // (vt2 (assertzext (truncate vt0:x), vt1)) ->3996  //     (vt2 (truncate (assertzext vt0:x, vt1)))3997  if (N0.getOpcode() == ISD::TRUNCATE) {3998    SDValue N1 = N->getOperand(1);3999    EVT ExtVT = cast<VTSDNode>(N1)->getVT();4000    SDLoc SL(N);4001 4002    SDValue Src = N0.getOperand(0);4003    EVT SrcVT = Src.getValueType();4004    if (SrcVT.bitsGE(ExtVT)) {4005      SDValue NewInReg = DAG.getNode(N->getOpcode(), SL, SrcVT, Src, N1);4006      return DAG.getNode(ISD::TRUNCATE, SL, N->getValueType(0), NewInReg);4007    }4008  }4009 4010  return SDValue();4011}4012 4013SDValue AMDGPUTargetLowering::performIntrinsicWOChainCombine(4014  SDNode *N, DAGCombinerInfo &DCI) const {4015  unsigned IID = N->getConstantOperandVal(0);4016  switch (IID) {4017  case Intrinsic::amdgcn_mul_i24:4018  case Intrinsic::amdgcn_mul_u24:4019  case Intrinsic::amdgcn_mulhi_i24:4020  case Intrinsic::amdgcn_mulhi_u24:4021    return simplifyMul24(N, DCI);4022  case Intrinsic::amdgcn_fract:4023  case Intrinsic::amdgcn_rsq:4024  case Intrinsic::amdgcn_rcp_legacy:4025  case Intrinsic::amdgcn_rsq_legacy:4026  case Intrinsic::amdgcn_rsq_clamp:4027  case Intrinsic::amdgcn_tanh:4028  case Intrinsic::amdgcn_prng_b32: {4029    // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted4030    SDValue Src = N->getOperand(1);4031    return Src.isUndef() ? Src : SDValue();4032  }4033  case Intrinsic::amdgcn_frexp_exp: {4034    // frexp_exp (fneg x) -> frexp_exp x4035    // frexp_exp (fabs x) -> frexp_exp x4036    // frexp_exp (fneg (fabs x)) -> frexp_exp x4037    SDValue Src = N->getOperand(1);4038    SDValue PeekSign = peekFPSignOps(Src);4039    if (PeekSign == Src)4040      return SDValue();4041    return SDValue(DCI.DAG.UpdateNodeOperands(N, N->getOperand(0), PeekSign),4042                   0);4043  }4044  default:4045    return SDValue();4046  }4047}4048 4049/// Split the 64-bit value \p LHS into two 32-bit components, and perform the4050/// binary operation \p Opc to it with the corresponding constant operands.4051SDValue AMDGPUTargetLowering::splitBinaryBitConstantOpImpl(4052  DAGCombinerInfo &DCI, const SDLoc &SL,4053  unsigned Opc, SDValue LHS,4054  uint32_t ValLo, uint32_t ValHi) const {4055  SelectionDAG &DAG = DCI.DAG;4056  SDValue Lo, Hi;4057  std::tie(Lo, Hi) = split64BitValue(LHS, DAG);4058 4059  SDValue LoRHS = DAG.getConstant(ValLo, SL, MVT::i32);4060  SDValue HiRHS = DAG.getConstant(ValHi, SL, MVT::i32);4061 4062  SDValue LoAnd = DAG.getNode(Opc, SL, MVT::i32, Lo, LoRHS);4063  SDValue HiAnd = DAG.getNode(Opc, SL, MVT::i32, Hi, HiRHS);4064 4065  // Re-visit the ands. It's possible we eliminated one of them and it could4066  // simplify the vector.4067  DCI.AddToWorklist(Lo.getNode());4068  DCI.AddToWorklist(Hi.getNode());4069 4070  SDValue Vec = DAG.getBuildVector(MVT::v2i32, SL, {LoAnd, HiAnd});4071  return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);4072}4073 4074SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,4075                                                DAGCombinerInfo &DCI) const {4076  EVT VT = N->getValueType(0);4077  SDValue LHS = N->getOperand(0);4078  SDValue RHS = N->getOperand(1);4079  ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);4080  SDLoc SL(N);4081  SelectionDAG &DAG = DCI.DAG;4082 4083  unsigned RHSVal;4084  if (CRHS) {4085    RHSVal = CRHS->getZExtValue();4086    if (!RHSVal)4087      return LHS;4088 4089    switch (LHS->getOpcode()) {4090    default:4091      break;4092    case ISD::ZERO_EXTEND:4093    case ISD::SIGN_EXTEND:4094    case ISD::ANY_EXTEND: {4095      SDValue X = LHS->getOperand(0);4096 4097      if (VT == MVT::i32 && RHSVal == 16 && X.getValueType() == MVT::i16 &&4098          isOperationLegal(ISD::BUILD_VECTOR, MVT::v2i16)) {4099        // Prefer build_vector as the canonical form if packed types are legal.4100        // (shl ([asz]ext i16:x), 16 -> build_vector 0, x4101        SDValue Vec = DAG.getBuildVector(4102            MVT::v2i16, SL,4103            {DAG.getConstant(0, SL, MVT::i16), LHS->getOperand(0)});4104        return DAG.getNode(ISD::BITCAST, SL, MVT::i32, Vec);4105      }4106 4107      // shl (ext x) => zext (shl x), if shift does not overflow int4108      if (VT != MVT::i64)4109        break;4110      KnownBits Known = DAG.computeKnownBits(X);4111      unsigned LZ = Known.countMinLeadingZeros();4112      if (LZ < RHSVal)4113        break;4114      EVT XVT = X.getValueType();4115      SDValue Shl = DAG.getNode(ISD::SHL, SL, XVT, X, SDValue(CRHS, 0));4116      return DAG.getZExtOrTrunc(Shl, SL, VT);4117    }4118    }4119  }4120 4121  if (VT.getScalarType() != MVT::i64)4122    return SDValue();4123 4124  // On some subtargets, 64-bit shift is a quarter rate instruction. In the4125  // common case, splitting this into a move and a 32-bit shift is faster and4126  // the same code size.4127  KnownBits Known = DAG.computeKnownBits(RHS);4128 4129  EVT ElementType = VT.getScalarType();4130  EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());4131  EVT TargetType = VT.isVector() ? VT.changeVectorElementType(TargetScalarType)4132                                 : TargetScalarType;4133 4134  if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())4135    return SDValue();4136  SDValue ShiftAmt;4137 4138  if (CRHS) {4139    ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,4140                               TargetType);4141  } else {4142    SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);4143    const SDValue ShiftMask =4144        DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);4145    // This AND instruction will clamp out of bounds shift values.4146    // It will also be removed during later instruction selection.4147    ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);4148  }4149 4150  SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);4151  SDValue NewShift =4152      DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());4153 4154  const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);4155  SDValue Vec;4156 4157  if (VT.isVector()) {4158    EVT ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());4159    unsigned NElts = TargetType.getVectorNumElements();4160    SmallVector<SDValue, 8> HiOps;4161    SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);4162 4163    DAG.ExtractVectorElements(NewShift, HiOps, 0, NElts);4164    for (unsigned I = 0; I != NElts; ++I)4165      HiAndLoOps[2 * I + 1] = HiOps[I];4166    Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);4167  } else {4168    EVT ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);4169    Vec = DAG.getBuildVector(ConcatType, SL, {Zero, NewShift});4170  }4171  return DAG.getNode(ISD::BITCAST, SL, VT, Vec);4172}4173 4174SDValue AMDGPUTargetLowering::performSraCombine(SDNode *N,4175                                                DAGCombinerInfo &DCI) const {4176  SDValue RHS = N->getOperand(1);4177  ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);4178  EVT VT = N->getValueType(0);4179  SDValue LHS = N->getOperand(0);4180  SelectionDAG &DAG = DCI.DAG;4181  SDLoc SL(N);4182 4183  if (VT.getScalarType() != MVT::i64)4184    return SDValue();4185 4186  // For C >= 324187  // i64 (sra x, C) -> (build_pair (sra hi_32(x), C - 32), sra hi_32(x), 31))4188 4189  // On some subtargets, 64-bit shift is a quarter rate instruction. In the4190  // common case, splitting this into a move and a 32-bit shift is faster and4191  // the same code size.4192  KnownBits Known = DAG.computeKnownBits(RHS);4193 4194  EVT ElementType = VT.getScalarType();4195  EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());4196  EVT TargetType = VT.isVector() ? VT.changeVectorElementType(TargetScalarType)4197                                 : TargetScalarType;4198 4199  if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())4200    return SDValue();4201 4202  SDValue ShiftFullAmt =4203      DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);4204  SDValue ShiftAmt;4205  if (CRHS) {4206    unsigned RHSVal = CRHS->getZExtValue();4207    ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,4208                               TargetType);4209  } else if (Known.getMinValue().getZExtValue() ==4210             (ElementType.getSizeInBits() - 1)) {4211    ShiftAmt = ShiftFullAmt;4212  } else {4213    SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);4214    const SDValue ShiftMask =4215        DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);4216    // This AND instruction will clamp out of bounds shift values.4217    // It will also be removed during later instruction selection.4218    ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);4219  }4220 4221  EVT ConcatType;4222  SDValue Hi;4223  SDLoc LHSSL(LHS);4224  // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi4225  if (VT.isVector()) {4226    unsigned NElts = TargetType.getVectorNumElements();4227    ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());4228    SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);4229    SmallVector<SDValue, 8> HiOps(NElts);4230    SmallVector<SDValue, 16> HiAndLoOps;4231 4232    DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, 0, NElts * 2);4233    for (unsigned I = 0; I != NElts; ++I) {4234      HiOps[I] = HiAndLoOps[2 * I + 1];4235    }4236    Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);4237  } else {4238    const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);4239    ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);4240    SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);4241    Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);4242  }4243 4244  KnownBits KnownLHS = DAG.computeKnownBits(LHS);4245  SDValue HiShift;4246  if (KnownLHS.isNegative()) {4247    HiShift = DAG.getAllOnesConstant(SL, TargetType);4248  } else {4249    Hi = DAG.getFreeze(Hi);4250    HiShift = DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftFullAmt);4251  }4252  SDValue NewShift =4253      DAG.getNode(ISD::SRA, SL, TargetType, Hi, ShiftAmt, N->getFlags());4254 4255  SDValue Vec;4256  if (VT.isVector()) {4257    unsigned NElts = TargetType.getVectorNumElements();4258    SmallVector<SDValue, 8> HiOps;4259    SmallVector<SDValue, 8> LoOps;4260    SmallVector<SDValue, 16> HiAndLoOps(NElts * 2);4261 4262    DAG.ExtractVectorElements(HiShift, HiOps, 0, NElts);4263    DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);4264    for (unsigned I = 0; I != NElts; ++I) {4265      HiAndLoOps[2 * I + 1] = HiOps[I];4266      HiAndLoOps[2 * I] = LoOps[I];4267    }4268    Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);4269  } else {4270    Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, HiShift});4271  }4272  return DAG.getNode(ISD::BITCAST, SL, VT, Vec);4273}4274 4275SDValue AMDGPUTargetLowering::performSrlCombine(SDNode *N,4276                                                DAGCombinerInfo &DCI) const {4277  SDValue RHS = N->getOperand(1);4278  ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);4279  EVT VT = N->getValueType(0);4280  SDValue LHS = N->getOperand(0);4281  SelectionDAG &DAG = DCI.DAG;4282  SDLoc SL(N);4283  unsigned RHSVal;4284 4285  if (CRHS) {4286    RHSVal = CRHS->getZExtValue();4287 4288    // fold (srl (and x, c1 << c2), c2) -> (and (srl(x, c2), c1)4289    // this improves the ability to match BFE patterns in isel.4290    if (LHS.getOpcode() == ISD::AND) {4291      if (auto *Mask = dyn_cast<ConstantSDNode>(LHS.getOperand(1))) {4292        unsigned MaskIdx, MaskLen;4293        if (Mask->getAPIntValue().isShiftedMask(MaskIdx, MaskLen) &&4294            MaskIdx == RHSVal) {4295          return DAG.getNode(ISD::AND, SL, VT,4296                             DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(0),4297                                         N->getOperand(1)),4298                             DAG.getNode(ISD::SRL, SL, VT, LHS.getOperand(1),4299                                         N->getOperand(1)));4300        }4301      }4302    }4303  }4304 4305  if (VT.getScalarType() != MVT::i64)4306    return SDValue();4307 4308  // for C >= 324309  // i64 (srl x, C) -> (build_pair (srl hi_32(x), C - 32), 0)4310 4311  // On some subtargets, 64-bit shift is a quarter rate instruction. In the4312  // common case, splitting this into a move and a 32-bit shift is faster and4313  // the same code size.4314  KnownBits Known = DAG.computeKnownBits(RHS);4315 4316  EVT ElementType = VT.getScalarType();4317  EVT TargetScalarType = ElementType.getHalfSizedIntegerVT(*DAG.getContext());4318  EVT TargetType = VT.isVector() ? VT.changeVectorElementType(TargetScalarType)4319                                 : TargetScalarType;4320 4321  if (Known.getMinValue().getZExtValue() < TargetScalarType.getSizeInBits())4322    return SDValue();4323 4324  SDValue ShiftAmt;4325  if (CRHS) {4326    ShiftAmt = DAG.getConstant(RHSVal - TargetScalarType.getSizeInBits(), SL,4327                               TargetType);4328  } else {4329    SDValue TruncShiftAmt = DAG.getNode(ISD::TRUNCATE, SL, TargetType, RHS);4330    const SDValue ShiftMask =4331        DAG.getConstant(TargetScalarType.getSizeInBits() - 1, SL, TargetType);4332    // This AND instruction will clamp out of bounds shift values.4333    // It will also be removed during later instruction selection.4334    ShiftAmt = DAG.getNode(ISD::AND, SL, TargetType, TruncShiftAmt, ShiftMask);4335  }4336 4337  const SDValue Zero = DAG.getConstant(0, SL, TargetScalarType);4338  EVT ConcatType;4339  SDValue Hi;4340  SDLoc LHSSL(LHS);4341  // Bitcast LHS into ConcatType so hi-half of source can be extracted into Hi4342  if (VT.isVector()) {4343    unsigned NElts = TargetType.getVectorNumElements();4344    ConcatType = TargetType.getDoubleNumVectorElementsVT(*DAG.getContext());4345    SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);4346    SmallVector<SDValue, 8> HiOps(NElts);4347    SmallVector<SDValue, 16> HiAndLoOps;4348 4349    DAG.ExtractVectorElements(SplitLHS, HiAndLoOps, /*Start=*/0, NElts * 2);4350    for (unsigned I = 0; I != NElts; ++I)4351      HiOps[I] = HiAndLoOps[2 * I + 1];4352    Hi = DAG.getNode(ISD::BUILD_VECTOR, LHSSL, TargetType, HiOps);4353  } else {4354    const SDValue One = DAG.getConstant(1, LHSSL, TargetScalarType);4355    ConcatType = EVT::getVectorVT(*DAG.getContext(), TargetType, 2);4356    SDValue SplitLHS = DAG.getNode(ISD::BITCAST, LHSSL, ConcatType, LHS);4357    Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, LHSSL, TargetType, SplitLHS, One);4358  }4359 4360  SDValue NewShift =4361      DAG.getNode(ISD::SRL, SL, TargetType, Hi, ShiftAmt, N->getFlags());4362 4363  SDValue Vec;4364  if (VT.isVector()) {4365    unsigned NElts = TargetType.getVectorNumElements();4366    SmallVector<SDValue, 8> LoOps;4367    SmallVector<SDValue, 16> HiAndLoOps(NElts * 2, Zero);4368 4369    DAG.ExtractVectorElements(NewShift, LoOps, 0, NElts);4370    for (unsigned I = 0; I != NElts; ++I)4371      HiAndLoOps[2 * I] = LoOps[I];4372    Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, ConcatType, HiAndLoOps);4373  } else {4374    Vec = DAG.getBuildVector(ConcatType, SL, {NewShift, Zero});4375  }4376  return DAG.getNode(ISD::BITCAST, SL, VT, Vec);4377}4378 4379SDValue AMDGPUTargetLowering::performTruncateCombine(4380  SDNode *N, DAGCombinerInfo &DCI) const {4381  SDLoc SL(N);4382  SelectionDAG &DAG = DCI.DAG;4383  EVT VT = N->getValueType(0);4384  SDValue Src = N->getOperand(0);4385 4386  // vt1 (truncate (bitcast (build_vector vt0:x, ...))) -> vt1 (bitcast vt0:x)4387  if (Src.getOpcode() == ISD::BITCAST && !VT.isVector()) {4388    SDValue Vec = Src.getOperand(0);4389    if (Vec.getOpcode() == ISD::BUILD_VECTOR) {4390      SDValue Elt0 = Vec.getOperand(0);4391      EVT EltVT = Elt0.getValueType();4392      if (VT.getFixedSizeInBits() <= EltVT.getFixedSizeInBits()) {4393        if (EltVT.isFloatingPoint()) {4394          Elt0 = DAG.getNode(ISD::BITCAST, SL,4395                             EltVT.changeTypeToInteger(), Elt0);4396        }4397 4398        return DAG.getNode(ISD::TRUNCATE, SL, VT, Elt0);4399      }4400    }4401  }4402 4403  // Equivalent of above for accessing the high element of a vector as an4404  // integer operation.4405  // trunc (srl (bitcast (build_vector x, y))), 16 -> trunc (bitcast y)4406  if (Src.getOpcode() == ISD::SRL && !VT.isVector()) {4407    if (auto *K = isConstOrConstSplat(Src.getOperand(1))) {4408      SDValue BV = stripBitcast(Src.getOperand(0));4409      if (BV.getOpcode() == ISD::BUILD_VECTOR) {4410        EVT SrcEltVT = BV.getOperand(0).getValueType();4411        unsigned SrcEltSize = SrcEltVT.getSizeInBits();4412        unsigned BitIndex = K->getZExtValue();4413        unsigned PartIndex = BitIndex / SrcEltSize;4414 4415        if (PartIndex * SrcEltSize == BitIndex &&4416            PartIndex < BV.getNumOperands()) {4417          if (SrcEltVT.getSizeInBits() == VT.getSizeInBits()) {4418            SDValue SrcElt =4419                DAG.getNode(ISD::BITCAST, SL, SrcEltVT.changeTypeToInteger(),4420                            BV.getOperand(PartIndex));4421            return DAG.getNode(ISD::TRUNCATE, SL, VT, SrcElt);4422          }4423        }4424      }4425    }4426  }4427 4428  // Partially shrink 64-bit shifts to 32-bit if reduced to 16-bit.4429  //4430  // i16 (trunc (srl i64:x, K)), K <= 16 ->4431  //     i16 (trunc (srl (i32 (trunc x), K)))4432  if (VT.getScalarSizeInBits() < 32) {4433    EVT SrcVT = Src.getValueType();4434    if (SrcVT.getScalarSizeInBits() > 32 &&4435        (Src.getOpcode() == ISD::SRL ||4436         Src.getOpcode() == ISD::SRA ||4437         Src.getOpcode() == ISD::SHL)) {4438      SDValue Amt = Src.getOperand(1);4439      KnownBits Known = DAG.computeKnownBits(Amt);4440 4441      // - For left shifts, do the transform as long as the shift4442      //   amount is still legal for i32, so when ShiftAmt < 32 (<= 31)4443      // - For right shift, do it if ShiftAmt <= (32 - Size) to avoid4444      //   losing information stored in the high bits when truncating.4445      const unsigned MaxCstSize =4446          (Src.getOpcode() == ISD::SHL) ? 31 : (32 - VT.getScalarSizeInBits());4447      if (Known.getMaxValue().ule(MaxCstSize)) {4448        EVT MidVT = VT.isVector() ?4449          EVT::getVectorVT(*DAG.getContext(), MVT::i32,4450                           VT.getVectorNumElements()) : MVT::i32;4451 4452        EVT NewShiftVT = getShiftAmountTy(MidVT, DAG.getDataLayout());4453        SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, MidVT,4454                                    Src.getOperand(0));4455        DCI.AddToWorklist(Trunc.getNode());4456 4457        if (Amt.getValueType() != NewShiftVT) {4458          Amt = DAG.getZExtOrTrunc(Amt, SL, NewShiftVT);4459          DCI.AddToWorklist(Amt.getNode());4460        }4461 4462        SDValue ShrunkShift = DAG.getNode(Src.getOpcode(), SL, MidVT,4463                                          Trunc, Amt);4464        return DAG.getNode(ISD::TRUNCATE, SL, VT, ShrunkShift);4465      }4466    }4467  }4468 4469  return SDValue();4470}4471 4472// We need to specifically handle i64 mul here to avoid unnecessary conversion4473// instructions. If we only match on the legalized i64 mul expansion,4474// SimplifyDemandedBits will be unable to remove them because there will be4475// multiple uses due to the separate mul + mulh[su].4476static SDValue getMul24(SelectionDAG &DAG, const SDLoc &SL,4477                        SDValue N0, SDValue N1, unsigned Size, bool Signed) {4478  if (Size <= 32) {4479    unsigned MulOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;4480    return DAG.getNode(MulOpc, SL, MVT::i32, N0, N1);4481  }4482 4483  unsigned MulLoOpc = Signed ? AMDGPUISD::MUL_I24 : AMDGPUISD::MUL_U24;4484  unsigned MulHiOpc = Signed ? AMDGPUISD::MULHI_I24 : AMDGPUISD::MULHI_U24;4485 4486  SDValue MulLo = DAG.getNode(MulLoOpc, SL, MVT::i32, N0, N1);4487  SDValue MulHi = DAG.getNode(MulHiOpc, SL, MVT::i32, N0, N1);4488 4489  return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, MulLo, MulHi);4490}4491 4492/// If \p V is an add of a constant 1, returns the other operand. Otherwise4493/// return SDValue().4494static SDValue getAddOneOp(const SDNode *V) {4495  if (V->getOpcode() != ISD::ADD)4496    return SDValue();4497 4498  return isOneConstant(V->getOperand(1)) ? V->getOperand(0) : SDValue();4499}4500 4501SDValue AMDGPUTargetLowering::performMulCombine(SDNode *N,4502                                                DAGCombinerInfo &DCI) const {4503  assert(N->getOpcode() == ISD::MUL);4504  EVT VT = N->getValueType(0);4505 4506  // Don't generate 24-bit multiplies on values that are in SGPRs, since4507  // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs4508  // unnecessarily). isDivergent() is used as an approximation of whether the4509  // value is in an SGPR.4510  if (!N->isDivergent())4511    return SDValue();4512 4513  unsigned Size = VT.getSizeInBits();4514  if (VT.isVector() || Size > 64)4515    return SDValue();4516 4517  SelectionDAG &DAG = DCI.DAG;4518  SDLoc DL(N);4519 4520  SDValue N0 = N->getOperand(0);4521  SDValue N1 = N->getOperand(1);4522 4523  // Undo InstCombine canonicalize X * (Y + 1) -> X * Y + X to enable mad4524  // matching.4525 4526  // mul x, (add y, 1) -> add (mul x, y), x4527  auto IsFoldableAdd = [](SDValue V) -> SDValue {4528    SDValue AddOp = getAddOneOp(V.getNode());4529    if (!AddOp)4530      return SDValue();4531 4532    if (V.hasOneUse() || all_of(V->users(), [](const SDNode *U) -> bool {4533          return U->getOpcode() == ISD::MUL;4534        }))4535      return AddOp;4536 4537    return SDValue();4538  };4539 4540  // FIXME: The selection pattern is not properly checking for commuted4541  // operands, so we have to place the mul in the LHS4542  if (SDValue MulOper = IsFoldableAdd(N0)) {4543    SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N1, MulOper);4544    return DAG.getNode(ISD::ADD, DL, VT, MulVal, N1);4545  }4546 4547  if (SDValue MulOper = IsFoldableAdd(N1)) {4548    SDValue MulVal = DAG.getNode(N->getOpcode(), DL, VT, N0, MulOper);4549    return DAG.getNode(ISD::ADD, DL, VT, MulVal, N0);4550  }4551 4552  // There are i16 integer mul/mad.4553  if (Subtarget->has16BitInsts() && VT.getScalarType().bitsLE(MVT::i16))4554    return SDValue();4555 4556  // SimplifyDemandedBits has the annoying habit of turning useful zero_extends4557  // in the source into any_extends if the result of the mul is truncated. Since4558  // we can assume the high bits are whatever we want, use the underlying value4559  // to avoid the unknown high bits from interfering.4560  if (N0.getOpcode() == ISD::ANY_EXTEND)4561    N0 = N0.getOperand(0);4562 4563  if (N1.getOpcode() == ISD::ANY_EXTEND)4564    N1 = N1.getOperand(0);4565 4566  SDValue Mul;4567 4568  if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {4569    N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);4570    N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);4571    Mul = getMul24(DAG, DL, N0, N1, Size, false);4572  } else if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {4573    N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);4574    N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);4575    Mul = getMul24(DAG, DL, N0, N1, Size, true);4576  } else {4577    return SDValue();4578  }4579 4580  // We need to use sext even for MUL_U24, because MUL_U24 is used4581  // for signed multiply of 8 and 16-bit types.4582  return DAG.getSExtOrTrunc(Mul, DL, VT);4583}4584 4585SDValue4586AMDGPUTargetLowering::performMulLoHiCombine(SDNode *N,4587                                            DAGCombinerInfo &DCI) const {4588  if (N->getValueType(0) != MVT::i32)4589    return SDValue();4590 4591  SelectionDAG &DAG = DCI.DAG;4592  SDLoc DL(N);4593 4594  bool Signed = N->getOpcode() == ISD::SMUL_LOHI;4595  SDValue N0 = N->getOperand(0);4596  SDValue N1 = N->getOperand(1);4597 4598  // SimplifyDemandedBits has the annoying habit of turning useful zero_extends4599  // in the source into any_extends if the result of the mul is truncated. Since4600  // we can assume the high bits are whatever we want, use the underlying value4601  // to avoid the unknown high bits from interfering.4602  if (N0.getOpcode() == ISD::ANY_EXTEND)4603    N0 = N0.getOperand(0);4604  if (N1.getOpcode() == ISD::ANY_EXTEND)4605    N1 = N1.getOperand(0);4606 4607  // Try to use two fast 24-bit multiplies (one for each half of the result)4608  // instead of one slow extending multiply.4609  unsigned LoOpcode = 0;4610  unsigned HiOpcode = 0;4611  if (Signed) {4612    if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {4613      N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);4614      N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);4615      LoOpcode = AMDGPUISD::MUL_I24;4616      HiOpcode = AMDGPUISD::MULHI_I24;4617    }4618  } else {4619    if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {4620      N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);4621      N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);4622      LoOpcode = AMDGPUISD::MUL_U24;4623      HiOpcode = AMDGPUISD::MULHI_U24;4624    }4625  }4626  if (!LoOpcode)4627    return SDValue();4628 4629  SDValue Lo = DAG.getNode(LoOpcode, DL, MVT::i32, N0, N1);4630  SDValue Hi = DAG.getNode(HiOpcode, DL, MVT::i32, N0, N1);4631  DCI.CombineTo(N, Lo, Hi);4632  return SDValue(N, 0);4633}4634 4635SDValue AMDGPUTargetLowering::performMulhsCombine(SDNode *N,4636                                                  DAGCombinerInfo &DCI) const {4637  EVT VT = N->getValueType(0);4638 4639  if (!Subtarget->hasMulI24() || VT.isVector())4640    return SDValue();4641 4642  // Don't generate 24-bit multiplies on values that are in SGPRs, since4643  // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs4644  // unnecessarily). isDivergent() is used as an approximation of whether the4645  // value is in an SGPR.4646  // This doesn't apply if no s_mul_hi is available (since we'll end up with a4647  // valu op anyway)4648  if (Subtarget->hasSMulHi() && !N->isDivergent())4649    return SDValue();4650 4651  SelectionDAG &DAG = DCI.DAG;4652  SDLoc DL(N);4653 4654  SDValue N0 = N->getOperand(0);4655  SDValue N1 = N->getOperand(1);4656 4657  if (!isI24(N0, DAG) || !isI24(N1, DAG))4658    return SDValue();4659 4660  N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);4661  N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);4662 4663  SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_I24, DL, MVT::i32, N0, N1);4664  DCI.AddToWorklist(Mulhi.getNode());4665  return DAG.getSExtOrTrunc(Mulhi, DL, VT);4666}4667 4668SDValue AMDGPUTargetLowering::performMulhuCombine(SDNode *N,4669                                                  DAGCombinerInfo &DCI) const {4670  EVT VT = N->getValueType(0);4671 4672  if (!Subtarget->hasMulU24() || VT.isVector() || VT.getSizeInBits() > 32)4673    return SDValue();4674 4675  // Don't generate 24-bit multiplies on values that are in SGPRs, since4676  // we only have a 32-bit scalar multiply (avoid values being moved to VGPRs4677  // unnecessarily). isDivergent() is used as an approximation of whether the4678  // value is in an SGPR.4679  // This doesn't apply if no s_mul_hi is available (since we'll end up with a4680  // valu op anyway)4681  if (Subtarget->hasSMulHi() && !N->isDivergent())4682    return SDValue();4683 4684  SelectionDAG &DAG = DCI.DAG;4685  SDLoc DL(N);4686 4687  SDValue N0 = N->getOperand(0);4688  SDValue N1 = N->getOperand(1);4689 4690  if (!isU24(N0, DAG) || !isU24(N1, DAG))4691    return SDValue();4692 4693  N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);4694  N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);4695 4696  SDValue Mulhi = DAG.getNode(AMDGPUISD::MULHI_U24, DL, MVT::i32, N0, N1);4697  DCI.AddToWorklist(Mulhi.getNode());4698  return DAG.getZExtOrTrunc(Mulhi, DL, VT);4699}4700 4701SDValue AMDGPUTargetLowering::getFFBX_U32(SelectionDAG &DAG,4702                                          SDValue Op,4703                                          const SDLoc &DL,4704                                          unsigned Opc) const {4705  EVT VT = Op.getValueType();4706  EVT LegalVT = getTypeToTransformTo(*DAG.getContext(), VT);4707  if (LegalVT != MVT::i32 && (Subtarget->has16BitInsts() &&4708                              LegalVT != MVT::i16))4709    return SDValue();4710 4711  if (VT != MVT::i32)4712    Op = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Op);4713 4714  SDValue FFBX = DAG.getNode(Opc, DL, MVT::i32, Op);4715  if (VT != MVT::i32)4716    FFBX = DAG.getNode(ISD::TRUNCATE, DL, VT, FFBX);4717 4718  return FFBX;4719}4720 4721// The native instructions return -1 on 0 input. Optimize out a select that4722// produces -1 on 0.4723//4724// TODO: If zero is not undef, we could also do this if the output is compared4725// against the bitwidth.4726//4727// TODO: Should probably combine against FFBH_U32 instead of ctlz directly.4728SDValue AMDGPUTargetLowering::performCtlz_CttzCombine(const SDLoc &SL, SDValue Cond,4729                                                 SDValue LHS, SDValue RHS,4730                                                 DAGCombinerInfo &DCI) const {4731  if (!isNullConstant(Cond.getOperand(1)))4732    return SDValue();4733 4734  SelectionDAG &DAG = DCI.DAG;4735  ISD::CondCode CCOpcode = cast<CondCodeSDNode>(Cond.getOperand(2))->get();4736  SDValue CmpLHS = Cond.getOperand(0);4737 4738  // select (setcc x, 0, eq), -1, (ctlz_zero_undef x) -> ffbh_u32 x4739  // select (setcc x, 0, eq), -1, (cttz_zero_undef x) -> ffbl_u32 x4740  if (CCOpcode == ISD::SETEQ &&4741      (isCtlzOpc(RHS.getOpcode()) || isCttzOpc(RHS.getOpcode())) &&4742      RHS.getOperand(0) == CmpLHS && isAllOnesConstant(LHS)) {4743    unsigned Opc =4744        isCttzOpc(RHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;4745    return getFFBX_U32(DAG, CmpLHS, SL, Opc);4746  }4747 4748  // select (setcc x, 0, ne), (ctlz_zero_undef x), -1 -> ffbh_u32 x4749  // select (setcc x, 0, ne), (cttz_zero_undef x), -1 -> ffbl_u32 x4750  if (CCOpcode == ISD::SETNE &&4751      (isCtlzOpc(LHS.getOpcode()) || isCttzOpc(LHS.getOpcode())) &&4752      LHS.getOperand(0) == CmpLHS && isAllOnesConstant(RHS)) {4753    unsigned Opc =4754        isCttzOpc(LHS.getOpcode()) ? AMDGPUISD::FFBL_B32 : AMDGPUISD::FFBH_U32;4755 4756    return getFFBX_U32(DAG, CmpLHS, SL, Opc);4757  }4758 4759  return SDValue();4760}4761 4762static SDValue distributeOpThroughSelect(TargetLowering::DAGCombinerInfo &DCI,4763                                         unsigned Op,4764                                         const SDLoc &SL,4765                                         SDValue Cond,4766                                         SDValue N1,4767                                         SDValue N2) {4768  SelectionDAG &DAG = DCI.DAG;4769  EVT VT = N1.getValueType();4770 4771  SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT, Cond,4772                                  N1.getOperand(0), N2.getOperand(0));4773  DCI.AddToWorklist(NewSelect.getNode());4774  return DAG.getNode(Op, SL, VT, NewSelect);4775}4776 4777// Pull a free FP operation out of a select so it may fold into uses.4778//4779// select c, (fneg x), (fneg y) -> fneg (select c, x, y)4780// select c, (fneg x), k -> fneg (select c, x, (fneg k))4781//4782// select c, (fabs x), (fabs y) -> fabs (select c, x, y)4783// select c, (fabs x), +k -> fabs (select c, x, k)4784SDValue4785AMDGPUTargetLowering::foldFreeOpFromSelect(TargetLowering::DAGCombinerInfo &DCI,4786                                           SDValue N) const {4787  SelectionDAG &DAG = DCI.DAG;4788  SDValue Cond = N.getOperand(0);4789  SDValue LHS = N.getOperand(1);4790  SDValue RHS = N.getOperand(2);4791 4792  EVT VT = N.getValueType();4793  if ((LHS.getOpcode() == ISD::FABS && RHS.getOpcode() == ISD::FABS) ||4794      (LHS.getOpcode() == ISD::FNEG && RHS.getOpcode() == ISD::FNEG)) {4795    if (!AMDGPUTargetLowering::allUsesHaveSourceMods(N.getNode()))4796      return SDValue();4797 4798    return distributeOpThroughSelect(DCI, LHS.getOpcode(),4799                                     SDLoc(N), Cond, LHS, RHS);4800  }4801 4802  bool Inv = false;4803  if (RHS.getOpcode() == ISD::FABS || RHS.getOpcode() == ISD::FNEG) {4804    std::swap(LHS, RHS);4805    Inv = true;4806  }4807 4808  // TODO: Support vector constants.4809  ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);4810  if ((LHS.getOpcode() == ISD::FNEG || LHS.getOpcode() == ISD::FABS) && CRHS &&4811      !selectSupportsSourceMods(N.getNode())) {4812    SDLoc SL(N);4813    // If one side is an fneg/fabs and the other is a constant, we can push the4814    // fneg/fabs down. If it's an fabs, the constant needs to be non-negative.4815    SDValue NewLHS = LHS.getOperand(0);4816    SDValue NewRHS = RHS;4817 4818    // Careful: if the neg can be folded up, don't try to pull it back down.4819    bool ShouldFoldNeg = true;4820 4821    if (NewLHS.hasOneUse()) {4822      unsigned Opc = NewLHS.getOpcode();4823      if (LHS.getOpcode() == ISD::FNEG && fnegFoldsIntoOp(NewLHS.getNode()))4824        ShouldFoldNeg = false;4825      if (LHS.getOpcode() == ISD::FABS && Opc == ISD::FMUL)4826        ShouldFoldNeg = false;4827    }4828 4829    if (ShouldFoldNeg) {4830      if (LHS.getOpcode() == ISD::FABS && CRHS->isNegative())4831        return SDValue();4832 4833      // We're going to be forced to use a source modifier anyway, there's no4834      // point to pulling the negate out unless we can get a size reduction by4835      // negating the constant.4836      //4837      // TODO: Generalize to use getCheaperNegatedExpression which doesn't know4838      // about cheaper constants.4839      if (NewLHS.getOpcode() == ISD::FABS &&4840          getConstantNegateCost(CRHS) != NegatibleCost::Cheaper)4841        return SDValue();4842 4843      if (!AMDGPUTargetLowering::allUsesHaveSourceMods(N.getNode()))4844        return SDValue();4845 4846      if (LHS.getOpcode() == ISD::FNEG)4847        NewRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);4848 4849      if (Inv)4850        std::swap(NewLHS, NewRHS);4851 4852      SDValue NewSelect = DAG.getNode(ISD::SELECT, SL, VT,4853                                      Cond, NewLHS, NewRHS);4854      DCI.AddToWorklist(NewSelect.getNode());4855      return DAG.getNode(LHS.getOpcode(), SL, VT, NewSelect);4856    }4857  }4858 4859  return SDValue();4860}4861 4862SDValue AMDGPUTargetLowering::performSelectCombine(SDNode *N,4863                                                   DAGCombinerInfo &DCI) const {4864  if (SDValue Folded = foldFreeOpFromSelect(DCI, SDValue(N, 0)))4865    return Folded;4866 4867  SDValue Cond = N->getOperand(0);4868  if (Cond.getOpcode() != ISD::SETCC)4869    return SDValue();4870 4871  EVT VT = N->getValueType(0);4872  SDValue LHS = Cond.getOperand(0);4873  SDValue RHS = Cond.getOperand(1);4874  SDValue CC = Cond.getOperand(2);4875 4876  SDValue True = N->getOperand(1);4877  SDValue False = N->getOperand(2);4878 4879  if (Cond.hasOneUse()) { // TODO: Look for multiple select uses.4880    SelectionDAG &DAG = DCI.DAG;4881    if (DAG.isConstantValueOfAnyType(True) &&4882        !DAG.isConstantValueOfAnyType(False)) {4883      // Swap cmp + select pair to move constant to false input.4884      // This will allow using VOPC cndmasks more often.4885      // select (setcc x, y), k, x -> select (setccinv x, y), x, k4886 4887      SDLoc SL(N);4888      ISD::CondCode NewCC =4889          getSetCCInverse(cast<CondCodeSDNode>(CC)->get(), LHS.getValueType());4890 4891      SDValue NewCond = DAG.getSetCC(SL, Cond.getValueType(), LHS, RHS, NewCC);4892      return DAG.getNode(ISD::SELECT, SL, VT, NewCond, False, True);4893    }4894 4895    if (VT == MVT::f32 && Subtarget->hasFminFmaxLegacy()) {4896      SDValue MinMax4897        = combineFMinMaxLegacy(SDLoc(N), VT, LHS, RHS, True, False, CC, DCI);4898      // Revisit this node so we can catch min3/max3/med3 patterns.4899      //DCI.AddToWorklist(MinMax.getNode());4900      return MinMax;4901    }4902  }4903 4904  // There's no reason to not do this if the condition has other uses.4905  return performCtlz_CttzCombine(SDLoc(N), Cond, True, False, DCI);4906}4907 4908static bool isInv2Pi(const APFloat &APF) {4909  static const APFloat KF16(APFloat::IEEEhalf(), APInt(16, 0x3118));4910  static const APFloat KF32(APFloat::IEEEsingle(), APInt(32, 0x3e22f983));4911  static const APFloat KF64(APFloat::IEEEdouble(), APInt(64, 0x3fc45f306dc9c882));4912 4913  return APF.bitwiseIsEqual(KF16) ||4914         APF.bitwiseIsEqual(KF32) ||4915         APF.bitwiseIsEqual(KF64);4916}4917 4918// 0 and 1.0 / (0.5 * pi) do not have inline immmediates, so there is an4919// additional cost to negate them.4920TargetLowering::NegatibleCost4921AMDGPUTargetLowering::getConstantNegateCost(const ConstantFPSDNode *C) const {4922  if (C->isZero())4923    return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;4924 4925  if (Subtarget->hasInv2PiInlineImm() && isInv2Pi(C->getValueAPF()))4926    return C->isNegative() ? NegatibleCost::Cheaper : NegatibleCost::Expensive;4927 4928  return NegatibleCost::Neutral;4929}4930 4931bool AMDGPUTargetLowering::isConstantCostlierToNegate(SDValue N) const {4932  if (const ConstantFPSDNode *C = isConstOrConstSplatFP(N))4933    return getConstantNegateCost(C) == NegatibleCost::Expensive;4934  return false;4935}4936 4937bool AMDGPUTargetLowering::isConstantCheaperToNegate(SDValue N) const {4938  if (const ConstantFPSDNode *C = isConstOrConstSplatFP(N))4939    return getConstantNegateCost(C) == NegatibleCost::Cheaper;4940  return false;4941}4942 4943static unsigned inverseMinMax(unsigned Opc) {4944  switch (Opc) {4945  case ISD::FMAXNUM:4946    return ISD::FMINNUM;4947  case ISD::FMINNUM:4948    return ISD::FMAXNUM;4949  case ISD::FMAXNUM_IEEE:4950    return ISD::FMINNUM_IEEE;4951  case ISD::FMINNUM_IEEE:4952    return ISD::FMAXNUM_IEEE;4953  case ISD::FMAXIMUM:4954    return ISD::FMINIMUM;4955  case ISD::FMINIMUM:4956    return ISD::FMAXIMUM;4957  case ISD::FMAXIMUMNUM:4958    return ISD::FMINIMUMNUM;4959  case ISD::FMINIMUMNUM:4960    return ISD::FMAXIMUMNUM;4961  case AMDGPUISD::FMAX_LEGACY:4962    return AMDGPUISD::FMIN_LEGACY;4963  case AMDGPUISD::FMIN_LEGACY:4964    return AMDGPUISD::FMAX_LEGACY;4965  default:4966    llvm_unreachable("invalid min/max opcode");4967  }4968}4969 4970/// \return true if it's profitable to try to push an fneg into its source4971/// instruction.4972bool AMDGPUTargetLowering::shouldFoldFNegIntoSrc(SDNode *N, SDValue N0) {4973  // If the input has multiple uses and we can either fold the negate down, or4974  // the other uses cannot, give up. This both prevents unprofitable4975  // transformations and infinite loops: we won't repeatedly try to fold around4976  // a negate that has no 'good' form.4977  if (N0.hasOneUse()) {4978    // This may be able to fold into the source, but at a code size cost. Don't4979    // fold if the fold into the user is free.4980    if (allUsesHaveSourceMods(N, 0))4981      return false;4982  } else {4983    if (fnegFoldsIntoOp(N0.getNode()) &&4984        (allUsesHaveSourceMods(N) || !allUsesHaveSourceMods(N0.getNode())))4985      return false;4986  }4987 4988  return true;4989}4990 4991SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N,4992                                                 DAGCombinerInfo &DCI) const {4993  SelectionDAG &DAG = DCI.DAG;4994  SDValue N0 = N->getOperand(0);4995  EVT VT = N->getValueType(0);4996 4997  unsigned Opc = N0.getOpcode();4998 4999  if (!shouldFoldFNegIntoSrc(N, N0))5000    return SDValue();5001 5002  SDLoc SL(N);5003  switch (Opc) {5004  case ISD::FADD: {5005    if (!mayIgnoreSignedZero(N0))5006      return SDValue();5007 5008    // (fneg (fadd x, y)) -> (fadd (fneg x), (fneg y))5009    SDValue LHS = N0.getOperand(0);5010    SDValue RHS = N0.getOperand(1);5011 5012    if (LHS.getOpcode() != ISD::FNEG)5013      LHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);5014    else5015      LHS = LHS.getOperand(0);5016 5017    if (RHS.getOpcode() != ISD::FNEG)5018      RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);5019    else5020      RHS = RHS.getOperand(0);5021 5022    SDValue Res = DAG.getNode(ISD::FADD, SL, VT, LHS, RHS, N0->getFlags());5023    if (Res.getOpcode() != ISD::FADD)5024      return SDValue(); // Op got folded away.5025    if (!N0.hasOneUse())5026      DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));5027    return Res;5028  }5029  case ISD::FMUL:5030  case AMDGPUISD::FMUL_LEGACY: {5031    // (fneg (fmul x, y)) -> (fmul x, (fneg y))5032    // (fneg (fmul_legacy x, y)) -> (fmul_legacy x, (fneg y))5033    SDValue LHS = N0.getOperand(0);5034    SDValue RHS = N0.getOperand(1);5035 5036    if (LHS.getOpcode() == ISD::FNEG)5037      LHS = LHS.getOperand(0);5038    else if (RHS.getOpcode() == ISD::FNEG)5039      RHS = RHS.getOperand(0);5040    else5041      RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);5042 5043    SDValue Res = DAG.getNode(Opc, SL, VT, LHS, RHS, N0->getFlags());5044    if (Res.getOpcode() != Opc)5045      return SDValue(); // Op got folded away.5046    if (!N0.hasOneUse())5047      DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));5048    return Res;5049  }5050  case ISD::FMA:5051  case ISD::FMAD: {5052    // TODO: handle llvm.amdgcn.fma.legacy5053    if (!mayIgnoreSignedZero(N0))5054      return SDValue();5055 5056    // (fneg (fma x, y, z)) -> (fma x, (fneg y), (fneg z))5057    SDValue LHS = N0.getOperand(0);5058    SDValue MHS = N0.getOperand(1);5059    SDValue RHS = N0.getOperand(2);5060 5061    if (LHS.getOpcode() == ISD::FNEG)5062      LHS = LHS.getOperand(0);5063    else if (MHS.getOpcode() == ISD::FNEG)5064      MHS = MHS.getOperand(0);5065    else5066      MHS = DAG.getNode(ISD::FNEG, SL, VT, MHS);5067 5068    if (RHS.getOpcode() != ISD::FNEG)5069      RHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);5070    else5071      RHS = RHS.getOperand(0);5072 5073    SDValue Res = DAG.getNode(Opc, SL, VT, LHS, MHS, RHS);5074    if (Res.getOpcode() != Opc)5075      return SDValue(); // Op got folded away.5076    if (!N0.hasOneUse())5077      DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));5078    return Res;5079  }5080  case ISD::FMAXNUM:5081  case ISD::FMINNUM:5082  case ISD::FMAXNUM_IEEE:5083  case ISD::FMINNUM_IEEE:5084  case ISD::FMINIMUM:5085  case ISD::FMAXIMUM:5086  case ISD::FMINIMUMNUM:5087  case ISD::FMAXIMUMNUM:5088  case AMDGPUISD::FMAX_LEGACY:5089  case AMDGPUISD::FMIN_LEGACY: {5090    // fneg (fmaxnum x, y) -> fminnum (fneg x), (fneg y)5091    // fneg (fminnum x, y) -> fmaxnum (fneg x), (fneg y)5092    // fneg (fmax_legacy x, y) -> fmin_legacy (fneg x), (fneg y)5093    // fneg (fmin_legacy x, y) -> fmax_legacy (fneg x), (fneg y)5094 5095    SDValue LHS = N0.getOperand(0);5096    SDValue RHS = N0.getOperand(1);5097 5098    // 0 doesn't have a negated inline immediate.5099    // TODO: This constant check should be generalized to other operations.5100    if (isConstantCostlierToNegate(RHS))5101      return SDValue();5102 5103    SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);5104    SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);5105    unsigned Opposite = inverseMinMax(Opc);5106 5107    SDValue Res = DAG.getNode(Opposite, SL, VT, NegLHS, NegRHS, N0->getFlags());5108    if (Res.getOpcode() != Opposite)5109      return SDValue(); // Op got folded away.5110    if (!N0.hasOneUse())5111      DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));5112    return Res;5113  }5114  case AMDGPUISD::FMED3: {5115    SDValue Ops[3];5116    for (unsigned I = 0; I < 3; ++I)5117      Ops[I] = DAG.getNode(ISD::FNEG, SL, VT, N0->getOperand(I), N0->getFlags());5118 5119    SDValue Res = DAG.getNode(AMDGPUISD::FMED3, SL, VT, Ops, N0->getFlags());5120    if (Res.getOpcode() != AMDGPUISD::FMED3)5121      return SDValue(); // Op got folded away.5122 5123    if (!N0.hasOneUse()) {5124      SDValue Neg = DAG.getNode(ISD::FNEG, SL, VT, Res);5125      DAG.ReplaceAllUsesWith(N0, Neg);5126 5127      for (SDNode *U : Neg->users())5128        DCI.AddToWorklist(U);5129    }5130 5131    return Res;5132  }5133  case ISD::FP_EXTEND:5134  case ISD::FTRUNC:5135  case ISD::FRINT:5136  case ISD::FNEARBYINT: // XXX - Should fround be handled?5137  case ISD::FROUNDEVEN:5138  case ISD::FSIN:5139  case ISD::FCANONICALIZE:5140  case AMDGPUISD::RCP:5141  case AMDGPUISD::RCP_LEGACY:5142  case AMDGPUISD::RCP_IFLAG:5143  case AMDGPUISD::SIN_HW: {5144    SDValue CvtSrc = N0.getOperand(0);5145    if (CvtSrc.getOpcode() == ISD::FNEG) {5146      // (fneg (fp_extend (fneg x))) -> (fp_extend x)5147      // (fneg (rcp (fneg x))) -> (rcp x)5148      return DAG.getNode(Opc, SL, VT, CvtSrc.getOperand(0));5149    }5150 5151    if (!N0.hasOneUse())5152      return SDValue();5153 5154    // (fneg (fp_extend x)) -> (fp_extend (fneg x))5155    // (fneg (rcp x)) -> (rcp (fneg x))5156    SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);5157    return DAG.getNode(Opc, SL, VT, Neg, N0->getFlags());5158  }5159  case ISD::FP_ROUND: {5160    SDValue CvtSrc = N0.getOperand(0);5161 5162    if (CvtSrc.getOpcode() == ISD::FNEG) {5163      // (fneg (fp_round (fneg x))) -> (fp_round x)5164      return DAG.getNode(ISD::FP_ROUND, SL, VT,5165                         CvtSrc.getOperand(0), N0.getOperand(1));5166    }5167 5168    if (!N0.hasOneUse())5169      return SDValue();5170 5171    // (fneg (fp_round x)) -> (fp_round (fneg x))5172    SDValue Neg = DAG.getNode(ISD::FNEG, SL, CvtSrc.getValueType(), CvtSrc);5173    return DAG.getNode(ISD::FP_ROUND, SL, VT, Neg, N0.getOperand(1));5174  }5175  case ISD::FP16_TO_FP: {5176    // v_cvt_f32_f16 supports source modifiers on pre-VI targets without legal5177    // f16, but legalization of f16 fneg ends up pulling it out of the source.5178    // Put the fneg back as a legal source operation that can be matched later.5179    SDLoc SL(N);5180 5181    SDValue Src = N0.getOperand(0);5182    EVT SrcVT = Src.getValueType();5183 5184    // fneg (fp16_to_fp x) -> fp16_to_fp (xor x, 0x8000)5185    SDValue IntFNeg = DAG.getNode(ISD::XOR, SL, SrcVT, Src,5186                                  DAG.getConstant(0x8000, SL, SrcVT));5187    return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFNeg);5188  }5189  case ISD::SELECT: {5190    // fneg (select c, a, b) -> select c, (fneg a), (fneg b)5191    // TODO: Invert conditions of foldFreeOpFromSelect5192    return SDValue();5193  }5194  case ISD::BITCAST: {5195    SDLoc SL(N);5196    SDValue BCSrc = N0.getOperand(0);5197    if (BCSrc.getOpcode() == ISD::BUILD_VECTOR) {5198      SDValue HighBits = BCSrc.getOperand(BCSrc.getNumOperands() - 1);5199      if (HighBits.getValueType().getSizeInBits() != 32 ||5200          !fnegFoldsIntoOp(HighBits.getNode()))5201        return SDValue();5202 5203      // f64 fneg only really needs to operate on the high half of of the5204      // register, so try to force it to an f32 operation to help make use of5205      // source modifiers.5206      //5207      //5208      // fneg (f64 (bitcast (build_vector x, y))) ->5209      // f64 (bitcast (build_vector (bitcast i32:x to f32),5210      //                            (fneg (bitcast i32:y to f32)))5211 5212      SDValue CastHi = DAG.getNode(ISD::BITCAST, SL, MVT::f32, HighBits);5213      SDValue NegHi = DAG.getNode(ISD::FNEG, SL, MVT::f32, CastHi);5214      SDValue CastBack =5215          DAG.getNode(ISD::BITCAST, SL, HighBits.getValueType(), NegHi);5216 5217      SmallVector<SDValue, 8> Ops(BCSrc->ops());5218      Ops.back() = CastBack;5219      DCI.AddToWorklist(NegHi.getNode());5220      SDValue Build =5221          DAG.getNode(ISD::BUILD_VECTOR, SL, BCSrc.getValueType(), Ops);5222      SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, Build);5223 5224      if (!N0.hasOneUse())5225        DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Result));5226      return Result;5227    }5228 5229    if (BCSrc.getOpcode() == ISD::SELECT && VT == MVT::f32 &&5230        BCSrc.hasOneUse()) {5231      // fneg (bitcast (f32 (select cond, i32:lhs, i32:rhs))) ->5232      //   select cond, (bitcast i32:lhs to f32), (bitcast i32:rhs to f32)5233 5234      // TODO: Cast back result for multiple uses is beneficial in some cases.5235 5236      SDValue LHS =5237          DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(1));5238      SDValue RHS =5239          DAG.getNode(ISD::BITCAST, SL, MVT::f32, BCSrc.getOperand(2));5240 5241      SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, LHS);5242      SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHS);5243 5244      return DAG.getNode(ISD::SELECT, SL, MVT::f32, BCSrc.getOperand(0), NegLHS,5245                         NegRHS);5246    }5247 5248    return SDValue();5249  }5250  default:5251    return SDValue();5252  }5253}5254 5255SDValue AMDGPUTargetLowering::performFAbsCombine(SDNode *N,5256                                                 DAGCombinerInfo &DCI) const {5257  SelectionDAG &DAG = DCI.DAG;5258  SDValue N0 = N->getOperand(0);5259 5260  if (!N0.hasOneUse())5261    return SDValue();5262 5263  switch (N0.getOpcode()) {5264  case ISD::FP16_TO_FP: {5265    assert(!Subtarget->has16BitInsts() && "should only see if f16 is illegal");5266    SDLoc SL(N);5267    SDValue Src = N0.getOperand(0);5268    EVT SrcVT = Src.getValueType();5269 5270    // fabs (fp16_to_fp x) -> fp16_to_fp (and x, 0x7fff)5271    SDValue IntFAbs = DAG.getNode(ISD::AND, SL, SrcVT, Src,5272                                  DAG.getConstant(0x7fff, SL, SrcVT));5273    return DAG.getNode(ISD::FP16_TO_FP, SL, N->getValueType(0), IntFAbs);5274  }5275  default:5276    return SDValue();5277  }5278}5279 5280SDValue AMDGPUTargetLowering::performRcpCombine(SDNode *N,5281                                                DAGCombinerInfo &DCI) const {5282  const auto *CFP = dyn_cast<ConstantFPSDNode>(N->getOperand(0));5283  if (!CFP)5284    return SDValue();5285 5286  // XXX - Should this flush denormals?5287  const APFloat &Val = CFP->getValueAPF();5288  APFloat One(Val.getSemantics(), "1.0");5289  return DCI.DAG.getConstantFP(One / Val, SDLoc(N), N->getValueType(0));5290}5291 5292SDValue AMDGPUTargetLowering::PerformDAGCombine(SDNode *N,5293                                                DAGCombinerInfo &DCI) const {5294  SelectionDAG &DAG = DCI.DAG;5295  SDLoc DL(N);5296 5297  switch(N->getOpcode()) {5298  default:5299    break;5300  case ISD::BITCAST: {5301    EVT DestVT = N->getValueType(0);5302 5303    // Push casts through vector builds. This helps avoid emitting a large5304    // number of copies when materializing floating point vector constants.5305    //5306    // vNt1 bitcast (vNt0 (build_vector t0:x, t0:y)) =>5307    //   vnt1 = build_vector (t1 (bitcast t0:x)), (t1 (bitcast t0:y))5308    if (DestVT.isVector()) {5309      SDValue Src = N->getOperand(0);5310      if (Src.getOpcode() == ISD::BUILD_VECTOR &&5311          (DCI.getDAGCombineLevel() < AfterLegalizeDAG ||5312           isOperationLegal(ISD::BUILD_VECTOR, DestVT))) {5313        EVT SrcVT = Src.getValueType();5314        unsigned NElts = DestVT.getVectorNumElements();5315 5316        if (SrcVT.getVectorNumElements() == NElts) {5317          EVT DestEltVT = DestVT.getVectorElementType();5318 5319          SmallVector<SDValue, 8> CastedElts;5320          SDLoc SL(N);5321          for (unsigned I = 0, E = SrcVT.getVectorNumElements(); I != E; ++I) {5322            SDValue Elt = Src.getOperand(I);5323            CastedElts.push_back(DAG.getNode(ISD::BITCAST, DL, DestEltVT, Elt));5324          }5325 5326          return DAG.getBuildVector(DestVT, SL, CastedElts);5327        }5328      }5329    }5330 5331    if (DestVT.getSizeInBits() != 64 || !DestVT.isVector())5332      break;5333 5334    // Fold bitcasts of constants.5335    //5336    // v2i32 (bitcast i64:k) -> build_vector lo_32(k), hi_32(k)5337    // TODO: Generalize and move to DAGCombiner5338    SDValue Src = N->getOperand(0);5339    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Src)) {5340      SDLoc SL(N);5341      uint64_t CVal = C->getZExtValue();5342      SDValue BV = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,5343                               DAG.getConstant(Lo_32(CVal), SL, MVT::i32),5344                               DAG.getConstant(Hi_32(CVal), SL, MVT::i32));5345      return DAG.getNode(ISD::BITCAST, SL, DestVT, BV);5346    }5347 5348    if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Src)) {5349      const APInt &Val = C->getValueAPF().bitcastToAPInt();5350      SDLoc SL(N);5351      uint64_t CVal = Val.getZExtValue();5352      SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,5353                                DAG.getConstant(Lo_32(CVal), SL, MVT::i32),5354                                DAG.getConstant(Hi_32(CVal), SL, MVT::i32));5355 5356      return DAG.getNode(ISD::BITCAST, SL, DestVT, Vec);5357    }5358 5359    break;5360  }5361  case ISD::SHL:5362  case ISD::SRA:5363  case ISD::SRL: {5364    // Range metadata can be invalidated when loads are converted to legal types5365    // (e.g. v2i64 -> v4i32).5366    // Try to convert vector shl/sra/srl before type legalization so that range5367    // metadata can be utilized.5368    if (!(N->getValueType(0).isVector() &&5369          DCI.getDAGCombineLevel() == BeforeLegalizeTypes) &&5370        DCI.getDAGCombineLevel() < AfterLegalizeDAG)5371      break;5372    if (N->getOpcode() == ISD::SHL)5373      return performShlCombine(N, DCI);5374    if (N->getOpcode() == ISD::SRA)5375      return performSraCombine(N, DCI);5376    return performSrlCombine(N, DCI);5377  }5378  case ISD::TRUNCATE:5379    return performTruncateCombine(N, DCI);5380  case ISD::MUL:5381    return performMulCombine(N, DCI);5382  case AMDGPUISD::MUL_U24:5383  case AMDGPUISD::MUL_I24: {5384    if (SDValue Simplified = simplifyMul24(N, DCI))5385      return Simplified;5386    break;5387  }5388  case AMDGPUISD::MULHI_I24:5389  case AMDGPUISD::MULHI_U24:5390    return simplifyMul24(N, DCI);5391  case ISD::SMUL_LOHI:5392  case ISD::UMUL_LOHI:5393    return performMulLoHiCombine(N, DCI);5394  case ISD::MULHS:5395    return performMulhsCombine(N, DCI);5396  case ISD::MULHU:5397    return performMulhuCombine(N, DCI);5398  case ISD::SELECT:5399    return performSelectCombine(N, DCI);5400  case ISD::FNEG:5401    return performFNegCombine(N, DCI);5402  case ISD::FABS:5403    return performFAbsCombine(N, DCI);5404  case AMDGPUISD::BFE_I32:5405  case AMDGPUISD::BFE_U32: {5406    assert(!N->getValueType(0).isVector() &&5407           "Vector handling of BFE not implemented");5408    ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));5409    if (!Width)5410      break;5411 5412    uint32_t WidthVal = Width->getZExtValue() & 0x1f;5413    if (WidthVal == 0)5414      return DAG.getConstant(0, DL, MVT::i32);5415 5416    ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));5417    if (!Offset)5418      break;5419 5420    SDValue BitsFrom = N->getOperand(0);5421    uint32_t OffsetVal = Offset->getZExtValue() & 0x1f;5422 5423    bool Signed = N->getOpcode() == AMDGPUISD::BFE_I32;5424 5425    if (OffsetVal == 0) {5426      // This is already sign / zero extended, so try to fold away extra BFEs.5427      unsigned SignBits =  Signed ? (32 - WidthVal + 1) : (32 - WidthVal);5428 5429      unsigned OpSignBits = DAG.ComputeNumSignBits(BitsFrom);5430      if (OpSignBits >= SignBits)5431        return BitsFrom;5432 5433      EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);5434      if (Signed) {5435        // This is a sign_extend_inreg. Replace it to take advantage of existing5436        // DAG Combines. If not eliminated, we will match back to BFE during5437        // selection.5438 5439        // TODO: The sext_inreg of extended types ends, although we can could5440        // handle them in a single BFE.5441        return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32, BitsFrom,5442                           DAG.getValueType(SmallVT));5443      }5444 5445      return DAG.getZeroExtendInReg(BitsFrom, DL, SmallVT);5446    }5447 5448    if (ConstantSDNode *CVal = dyn_cast<ConstantSDNode>(BitsFrom)) {5449      if (Signed) {5450        return constantFoldBFE<int32_t>(DAG,5451                                        CVal->getSExtValue(),5452                                        OffsetVal,5453                                        WidthVal,5454                                        DL);5455      }5456 5457      return constantFoldBFE<uint32_t>(DAG,5458                                       CVal->getZExtValue(),5459                                       OffsetVal,5460                                       WidthVal,5461                                       DL);5462    }5463 5464    if ((OffsetVal + WidthVal) >= 32 &&5465        !(Subtarget->hasSDWA() && OffsetVal == 16 && WidthVal == 16)) {5466      SDValue ShiftVal = DAG.getConstant(OffsetVal, DL, MVT::i32);5467      return DAG.getNode(Signed ? ISD::SRA : ISD::SRL, DL, MVT::i32,5468                         BitsFrom, ShiftVal);5469    }5470 5471    if (BitsFrom.hasOneUse()) {5472      APInt Demanded = APInt::getBitsSet(32,5473                                         OffsetVal,5474                                         OffsetVal + WidthVal);5475 5476      KnownBits Known;5477      TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),5478                                            !DCI.isBeforeLegalizeOps());5479      const TargetLowering &TLI = DAG.getTargetLoweringInfo();5480      if (TLI.ShrinkDemandedConstant(BitsFrom, Demanded, TLO) ||5481          TLI.SimplifyDemandedBits(BitsFrom, Demanded, Known, TLO)) {5482        DCI.CommitTargetLoweringOpt(TLO);5483      }5484    }5485 5486    break;5487  }5488  case ISD::LOAD:5489    return performLoadCombine(N, DCI);5490  case ISD::STORE:5491    return performStoreCombine(N, DCI);5492  case AMDGPUISD::RCP:5493  case AMDGPUISD::RCP_IFLAG:5494    return performRcpCombine(N, DCI);5495  case ISD::AssertZext:5496  case ISD::AssertSext:5497    return performAssertSZExtCombine(N, DCI);5498  case ISD::INTRINSIC_WO_CHAIN:5499    return performIntrinsicWOChainCombine(N, DCI);5500  case AMDGPUISD::FMAD_FTZ: {5501    SDValue N0 = N->getOperand(0);5502    SDValue N1 = N->getOperand(1);5503    SDValue N2 = N->getOperand(2);5504    EVT VT = N->getValueType(0);5505 5506    // FMAD_FTZ is a FMAD + flush denormals to zero.5507    // We flush the inputs, the intermediate step, and the output.5508    ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);5509    ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);5510    ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2);5511    if (N0CFP && N1CFP && N2CFP) {5512      const auto FTZ = [](const APFloat &V) {5513        if (V.isDenormal()) {5514          APFloat Zero(V.getSemantics(), 0);5515          return V.isNegative() ? -Zero : Zero;5516        }5517        return V;5518      };5519 5520      APFloat V0 = FTZ(N0CFP->getValueAPF());5521      APFloat V1 = FTZ(N1CFP->getValueAPF());5522      APFloat V2 = FTZ(N2CFP->getValueAPF());5523      V0.multiply(V1, APFloat::rmNearestTiesToEven);5524      V0 = FTZ(V0);5525      V0.add(V2, APFloat::rmNearestTiesToEven);5526      return DAG.getConstantFP(FTZ(V0), DL, VT);5527    }5528    break;5529  }5530  }5531  return SDValue();5532}5533 5534//===----------------------------------------------------------------------===//5535// Helper functions5536//===----------------------------------------------------------------------===//5537 5538SDValue AMDGPUTargetLowering::CreateLiveInRegister(SelectionDAG &DAG,5539                                                   const TargetRegisterClass *RC,5540                                                   Register Reg, EVT VT,5541                                                   const SDLoc &SL,5542                                                   bool RawReg) const {5543  MachineFunction &MF = DAG.getMachineFunction();5544  MachineRegisterInfo &MRI = MF.getRegInfo();5545  Register VReg;5546 5547  if (!MRI.isLiveIn(Reg)) {5548    VReg = MRI.createVirtualRegister(RC);5549    MRI.addLiveIn(Reg, VReg);5550  } else {5551    VReg = MRI.getLiveInVirtReg(Reg);5552  }5553 5554  if (RawReg)5555    return DAG.getRegister(VReg, VT);5556 5557  return DAG.getCopyFromReg(DAG.getEntryNode(), SL, VReg, VT);5558}5559 5560// This may be called multiple times, and nothing prevents creating multiple5561// objects at the same offset. See if we already defined this object.5562static int getOrCreateFixedStackObject(MachineFrameInfo &MFI, unsigned Size,5563                                       int64_t Offset) {5564  for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {5565    if (MFI.getObjectOffset(I) == Offset) {5566      assert(MFI.getObjectSize(I) == Size);5567      return I;5568    }5569  }5570 5571  return MFI.CreateFixedObject(Size, Offset, true);5572}5573 5574SDValue AMDGPUTargetLowering::loadStackInputValue(SelectionDAG &DAG,5575                                                  EVT VT,5576                                                  const SDLoc &SL,5577                                                  int64_t Offset) const {5578  MachineFunction &MF = DAG.getMachineFunction();5579  MachineFrameInfo &MFI = MF.getFrameInfo();5580  int FI = getOrCreateFixedStackObject(MFI, VT.getStoreSize(), Offset);5581 5582  auto SrcPtrInfo = MachinePointerInfo::getStack(MF, Offset);5583  SDValue Ptr = DAG.getFrameIndex(FI, MVT::i32);5584 5585  return DAG.getLoad(VT, SL, DAG.getEntryNode(), Ptr, SrcPtrInfo, Align(4),5586                     MachineMemOperand::MODereferenceable |5587                         MachineMemOperand::MOInvariant);5588}5589 5590SDValue AMDGPUTargetLowering::storeStackInputValue(SelectionDAG &DAG,5591                                                   const SDLoc &SL,5592                                                   SDValue Chain,5593                                                   SDValue ArgVal,5594                                                   int64_t Offset) const {5595  MachineFunction &MF = DAG.getMachineFunction();5596  MachinePointerInfo DstInfo = MachinePointerInfo::getStack(MF, Offset);5597  const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();5598 5599  SDValue Ptr = DAG.getConstant(Offset, SL, MVT::i32);5600  // Stores to the argument stack area are relative to the stack pointer.5601  SDValue SP =5602      DAG.getCopyFromReg(Chain, SL, Info->getStackPtrOffsetReg(), MVT::i32);5603  Ptr = DAG.getNode(ISD::ADD, SL, MVT::i32, SP, Ptr);5604  SDValue Store = DAG.getStore(Chain, SL, ArgVal, Ptr, DstInfo, Align(4),5605                               MachineMemOperand::MODereferenceable);5606  return Store;5607}5608 5609SDValue AMDGPUTargetLowering::loadInputValue(SelectionDAG &DAG,5610                                             const TargetRegisterClass *RC,5611                                             EVT VT, const SDLoc &SL,5612                                             const ArgDescriptor &Arg) const {5613  assert(Arg && "Attempting to load missing argument");5614 5615  SDValue V = Arg.isRegister() ?5616    CreateLiveInRegister(DAG, RC, Arg.getRegister(), VT, SL) :5617    loadStackInputValue(DAG, VT, SL, Arg.getStackOffset());5618 5619  if (!Arg.isMasked())5620    return V;5621 5622  unsigned Mask = Arg.getMask();5623  unsigned Shift = llvm::countr_zero<unsigned>(Mask);5624  V = DAG.getNode(ISD::SRL, SL, VT, V,5625                  DAG.getShiftAmountConstant(Shift, VT, SL));5626  return DAG.getNode(ISD::AND, SL, VT, V,5627                     DAG.getConstant(Mask >> Shift, SL, VT));5628}5629 5630uint32_t AMDGPUTargetLowering::getImplicitParameterOffset(5631    uint64_t ExplicitKernArgSize, const ImplicitParameter Param) const {5632  unsigned ExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();5633  const Align Alignment = Subtarget->getAlignmentForImplicitArgPtr();5634  uint64_t ArgOffset =5635      alignTo(ExplicitKernArgSize, Alignment) + ExplicitArgOffset;5636  switch (Param) {5637  case FIRST_IMPLICIT:5638    return ArgOffset;5639  case PRIVATE_BASE:5640    return ArgOffset + AMDGPU::ImplicitArg::PRIVATE_BASE_OFFSET;5641  case SHARED_BASE:5642    return ArgOffset + AMDGPU::ImplicitArg::SHARED_BASE_OFFSET;5643  case QUEUE_PTR:5644    return ArgOffset + AMDGPU::ImplicitArg::QUEUE_PTR_OFFSET;5645  }5646  llvm_unreachable("unexpected implicit parameter type");5647}5648 5649uint32_t AMDGPUTargetLowering::getImplicitParameterOffset(5650    const MachineFunction &MF, const ImplicitParameter Param) const {5651  const AMDGPUMachineFunction *MFI = MF.getInfo<AMDGPUMachineFunction>();5652  return getImplicitParameterOffset(MFI->getExplicitKernArgSize(), Param);5653}5654 5655SDValue AMDGPUTargetLowering::getSqrtEstimate(SDValue Operand,5656                                              SelectionDAG &DAG, int Enabled,5657                                              int &RefinementSteps,5658                                              bool &UseOneConstNR,5659                                              bool Reciprocal) const {5660  EVT VT = Operand.getValueType();5661 5662  if (VT == MVT::f32) {5663    RefinementSteps = 0;5664    return DAG.getNode(AMDGPUISD::RSQ, SDLoc(Operand), VT, Operand);5665  }5666 5667  // TODO: There is also f64 rsq instruction, but the documentation is less5668  // clear on its precision.5669 5670  return SDValue();5671}5672 5673SDValue AMDGPUTargetLowering::getRecipEstimate(SDValue Operand,5674                                               SelectionDAG &DAG, int Enabled,5675                                               int &RefinementSteps) const {5676  EVT VT = Operand.getValueType();5677 5678  if (VT == MVT::f32) {5679    // Reciprocal, < 1 ulp error.5680    //5681    // This reciprocal approximation converges to < 0.5 ulp error with one5682    // newton rhapson performed with two fused multiple adds (FMAs).5683 5684    RefinementSteps = 0;5685    return DAG.getNode(AMDGPUISD::RCP, SDLoc(Operand), VT, Operand);5686  }5687 5688  // TODO: There is also f64 rcp instruction, but the documentation is less5689  // clear on its precision.5690 5691  return SDValue();5692}5693 5694static unsigned workitemIntrinsicDim(unsigned ID) {5695  switch (ID) {5696  case Intrinsic::amdgcn_workitem_id_x:5697    return 0;5698  case Intrinsic::amdgcn_workitem_id_y:5699    return 1;5700  case Intrinsic::amdgcn_workitem_id_z:5701    return 2;5702  default:5703    llvm_unreachable("not a workitem intrinsic");5704  }5705}5706 5707void AMDGPUTargetLowering::computeKnownBitsForTargetNode(5708    const SDValue Op, KnownBits &Known,5709    const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const {5710 5711  Known.resetAll(); // Don't know anything.5712 5713  unsigned Opc = Op.getOpcode();5714 5715  switch (Opc) {5716  default:5717    break;5718  case AMDGPUISD::CARRY:5719  case AMDGPUISD::BORROW: {5720    Known.Zero = APInt::getHighBitsSet(32, 31);5721    break;5722  }5723 5724  case AMDGPUISD::BFE_I32:5725  case AMDGPUISD::BFE_U32: {5726    ConstantSDNode *CWidth = dyn_cast<ConstantSDNode>(Op.getOperand(2));5727    if (!CWidth)5728      return;5729 5730    uint32_t Width = CWidth->getZExtValue() & 0x1f;5731 5732    if (Opc == AMDGPUISD::BFE_U32)5733      Known.Zero = APInt::getHighBitsSet(32, 32 - Width);5734 5735    break;5736  }5737  case AMDGPUISD::FP_TO_FP16: {5738    unsigned BitWidth = Known.getBitWidth();5739 5740    // High bits are zero.5741    Known.Zero = APInt::getHighBitsSet(BitWidth, BitWidth - 16);5742    break;5743  }5744  case AMDGPUISD::MUL_U24:5745  case AMDGPUISD::MUL_I24: {5746    KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);5747    KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);5748    unsigned TrailZ = LHSKnown.countMinTrailingZeros() +5749                      RHSKnown.countMinTrailingZeros();5750    Known.Zero.setLowBits(std::min(TrailZ, 32u));5751    // Skip extra check if all bits are known zeros.5752    if (TrailZ >= 32)5753      break;5754 5755    // Truncate to 24 bits.5756    LHSKnown = LHSKnown.trunc(24);5757    RHSKnown = RHSKnown.trunc(24);5758 5759    if (Opc == AMDGPUISD::MUL_I24) {5760      unsigned LHSValBits = LHSKnown.countMaxSignificantBits();5761      unsigned RHSValBits = RHSKnown.countMaxSignificantBits();5762      unsigned MaxValBits = LHSValBits + RHSValBits;5763      if (MaxValBits > 32)5764        break;5765      unsigned SignBits = 32 - MaxValBits + 1;5766      bool LHSNegative = LHSKnown.isNegative();5767      bool LHSNonNegative = LHSKnown.isNonNegative();5768      bool LHSPositive = LHSKnown.isStrictlyPositive();5769      bool RHSNegative = RHSKnown.isNegative();5770      bool RHSNonNegative = RHSKnown.isNonNegative();5771      bool RHSPositive = RHSKnown.isStrictlyPositive();5772 5773      if ((LHSNonNegative && RHSNonNegative) || (LHSNegative && RHSNegative))5774        Known.Zero.setHighBits(SignBits);5775      else if ((LHSNegative && RHSPositive) || (LHSPositive && RHSNegative))5776        Known.One.setHighBits(SignBits);5777    } else {5778      unsigned LHSValBits = LHSKnown.countMaxActiveBits();5779      unsigned RHSValBits = RHSKnown.countMaxActiveBits();5780      unsigned MaxValBits = LHSValBits + RHSValBits;5781      if (MaxValBits >= 32)5782        break;5783      Known.Zero.setBitsFrom(MaxValBits);5784    }5785    break;5786  }5787  case AMDGPUISD::PERM: {5788    ConstantSDNode *CMask = dyn_cast<ConstantSDNode>(Op.getOperand(2));5789    if (!CMask)5790      return;5791 5792    KnownBits LHSKnown = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);5793    KnownBits RHSKnown = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);5794    unsigned Sel = CMask->getZExtValue();5795 5796    for (unsigned I = 0; I < 32; I += 8) {5797      unsigned SelBits = Sel & 0xff;5798      if (SelBits < 4) {5799        SelBits *= 8;5800        Known.One |= ((RHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;5801        Known.Zero |= ((RHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;5802      } else if (SelBits < 7) {5803        SelBits = (SelBits & 3) * 8;5804        Known.One |= ((LHSKnown.One.getZExtValue() >> SelBits) & 0xff) << I;5805        Known.Zero |= ((LHSKnown.Zero.getZExtValue() >> SelBits) & 0xff) << I;5806      } else if (SelBits == 0x0c) {5807        Known.Zero |= 0xFFull << I;5808      } else if (SelBits > 0x0c) {5809        Known.One |= 0xFFull << I;5810      }5811      Sel >>= 8;5812    }5813    break;5814  }5815  case AMDGPUISD::BUFFER_LOAD_UBYTE:  {5816    Known.Zero.setHighBits(24);5817    break;5818  }5819  case AMDGPUISD::BUFFER_LOAD_USHORT: {5820    Known.Zero.setHighBits(16);5821    break;5822  }5823  case AMDGPUISD::LDS: {5824    auto *GA = cast<GlobalAddressSDNode>(Op.getOperand(0).getNode());5825    Align Alignment = GA->getGlobal()->getPointerAlignment(DAG.getDataLayout());5826 5827    Known.Zero.setHighBits(16);5828    Known.Zero.setLowBits(Log2(Alignment));5829    break;5830  }5831  case AMDGPUISD::SMIN3:5832  case AMDGPUISD::SMAX3:5833  case AMDGPUISD::SMED3:5834  case AMDGPUISD::UMIN3:5835  case AMDGPUISD::UMAX3:5836  case AMDGPUISD::UMED3: {5837    KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);5838    if (Known2.isUnknown())5839      break;5840 5841    KnownBits Known1 = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);5842    if (Known1.isUnknown())5843      break;5844 5845    KnownBits Known0 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);5846    if (Known0.isUnknown())5847      break;5848 5849    // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.5850    Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;5851    Known.One = Known0.One & Known1.One & Known2.One;5852    break;5853  }5854  case ISD::INTRINSIC_WO_CHAIN: {5855    unsigned IID = Op.getConstantOperandVal(0);5856    switch (IID) {5857    case Intrinsic::amdgcn_workitem_id_x:5858    case Intrinsic::amdgcn_workitem_id_y:5859    case Intrinsic::amdgcn_workitem_id_z: {5860      unsigned MaxValue = Subtarget->getMaxWorkitemID(5861          DAG.getMachineFunction().getFunction(), workitemIntrinsicDim(IID));5862      Known.Zero.setHighBits(llvm::countl_zero(MaxValue));5863      break;5864    }5865    default:5866      break;5867    }5868  }5869  }5870}5871 5872unsigned AMDGPUTargetLowering::ComputeNumSignBitsForTargetNode(5873    SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,5874    unsigned Depth) const {5875  switch (Op.getOpcode()) {5876  case AMDGPUISD::BFE_I32: {5877    ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));5878    if (!Width)5879      return 1;5880 5881    unsigned SignBits = 32 - Width->getZExtValue() + 1;5882    if (!isNullConstant(Op.getOperand(1)))5883      return SignBits;5884 5885    // TODO: Could probably figure something out with non-0 offsets.5886    unsigned Op0SignBits = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);5887    return std::max(SignBits, Op0SignBits);5888  }5889 5890  case AMDGPUISD::BFE_U32: {5891    ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));5892    return Width ? 32 - (Width->getZExtValue() & 0x1f) : 1;5893  }5894 5895  case AMDGPUISD::CARRY:5896  case AMDGPUISD::BORROW:5897    return 31;5898  case AMDGPUISD::BUFFER_LOAD_BYTE:5899    return 25;5900  case AMDGPUISD::BUFFER_LOAD_SHORT:5901    return 17;5902  case AMDGPUISD::BUFFER_LOAD_UBYTE:5903    return 24;5904  case AMDGPUISD::BUFFER_LOAD_USHORT:5905    return 16;5906  case AMDGPUISD::FP_TO_FP16:5907    return 16;5908  case AMDGPUISD::SMIN3:5909  case AMDGPUISD::SMAX3:5910  case AMDGPUISD::SMED3:5911  case AMDGPUISD::UMIN3:5912  case AMDGPUISD::UMAX3:5913  case AMDGPUISD::UMED3: {5914    unsigned Tmp2 = DAG.ComputeNumSignBits(Op.getOperand(2), Depth + 1);5915    if (Tmp2 == 1)5916      return 1; // Early out.5917 5918    unsigned Tmp1 = DAG.ComputeNumSignBits(Op.getOperand(1), Depth + 1);5919    if (Tmp1 == 1)5920      return 1; // Early out.5921 5922    unsigned Tmp0 = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);5923    if (Tmp0 == 1)5924      return 1; // Early out.5925 5926    return std::min({Tmp0, Tmp1, Tmp2});5927  }5928  default:5929    return 1;5930  }5931}5932 5933unsigned AMDGPUTargetLowering::computeNumSignBitsForTargetInstr(5934    GISelValueTracking &Analysis, Register R, const APInt &DemandedElts,5935    const MachineRegisterInfo &MRI, unsigned Depth) const {5936  const MachineInstr *MI = MRI.getVRegDef(R);5937  if (!MI)5938    return 1;5939 5940  // TODO: Check range metadata on MMO.5941  switch (MI->getOpcode()) {5942  case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:5943    return 25;5944  case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:5945    return 17;5946  case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:5947    return 24;5948  case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:5949    return 16;5950  case AMDGPU::G_AMDGPU_SMED3:5951  case AMDGPU::G_AMDGPU_UMED3: {5952    auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();5953    unsigned Tmp2 = Analysis.computeNumSignBits(Src2, DemandedElts, Depth + 1);5954    if (Tmp2 == 1)5955      return 1;5956    unsigned Tmp1 = Analysis.computeNumSignBits(Src1, DemandedElts, Depth + 1);5957    if (Tmp1 == 1)5958      return 1;5959    unsigned Tmp0 = Analysis.computeNumSignBits(Src0, DemandedElts, Depth + 1);5960    if (Tmp0 == 1)5961      return 1;5962    return std::min({Tmp0, Tmp1, Tmp2});5963  }5964  default:5965    return 1;5966  }5967}5968 5969bool AMDGPUTargetLowering::canCreateUndefOrPoisonForTargetNode(5970    SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,5971    bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const {5972  unsigned Opcode = Op.getOpcode();5973  switch (Opcode) {5974  case AMDGPUISD::BFE_I32:5975  case AMDGPUISD::BFE_U32:5976    return false;5977  }5978  return TargetLowering::canCreateUndefOrPoisonForTargetNode(5979      Op, DemandedElts, DAG, PoisonOnly, ConsiderFlags, Depth);5980}5981 5982bool AMDGPUTargetLowering::isKnownNeverNaNForTargetNode(5983    SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN,5984    unsigned Depth) const {5985  unsigned Opcode = Op.getOpcode();5986  switch (Opcode) {5987  case AMDGPUISD::FMIN_LEGACY:5988  case AMDGPUISD::FMAX_LEGACY: {5989    if (SNaN)5990      return true;5991 5992    // TODO: Can check no nans on one of the operands for each one, but which5993    // one?5994    return false;5995  }5996  case AMDGPUISD::FMUL_LEGACY:5997  case AMDGPUISD::CVT_PKRTZ_F16_F32: {5998    if (SNaN)5999      return true;6000    return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&6001           DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);6002  }6003  case AMDGPUISD::FMED3:6004  case AMDGPUISD::FMIN3:6005  case AMDGPUISD::FMAX3:6006  case AMDGPUISD::FMINIMUM3:6007  case AMDGPUISD::FMAXIMUM3:6008  case AMDGPUISD::FMAD_FTZ: {6009    if (SNaN)6010      return true;6011    return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&6012           DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&6013           DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);6014  }6015  case AMDGPUISD::CVT_F32_UBYTE0:6016  case AMDGPUISD::CVT_F32_UBYTE1:6017  case AMDGPUISD::CVT_F32_UBYTE2:6018  case AMDGPUISD::CVT_F32_UBYTE3:6019    return true;6020 6021  case AMDGPUISD::RCP:6022  case AMDGPUISD::RSQ:6023  case AMDGPUISD::RCP_LEGACY:6024  case AMDGPUISD::RSQ_CLAMP: {6025    if (SNaN)6026      return true;6027 6028    // TODO: Need is known positive check.6029    return false;6030  }6031  case ISD::FLDEXP:6032  case AMDGPUISD::FRACT: {6033    if (SNaN)6034      return true;6035    return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);6036  }6037  case AMDGPUISD::DIV_SCALE:6038  case AMDGPUISD::DIV_FMAS:6039  case AMDGPUISD::DIV_FIXUP:6040    // TODO: Refine on operands.6041    return SNaN;6042  case AMDGPUISD::SIN_HW:6043  case AMDGPUISD::COS_HW: {6044    // TODO: Need check for infinity6045    return SNaN;6046  }6047  case ISD::INTRINSIC_WO_CHAIN: {6048    unsigned IntrinsicID = Op.getConstantOperandVal(0);6049    // TODO: Handle more intrinsics6050    switch (IntrinsicID) {6051    case Intrinsic::amdgcn_cubeid:6052    case Intrinsic::amdgcn_cvt_off_f32_i4:6053      return true;6054 6055    case Intrinsic::amdgcn_frexp_mant: {6056      if (SNaN)6057        return true;6058      return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);6059    }6060    case Intrinsic::amdgcn_cvt_pkrtz: {6061      if (SNaN)6062        return true;6063      return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&6064             DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);6065    }6066    case Intrinsic::amdgcn_rcp:6067    case Intrinsic::amdgcn_rsq:6068    case Intrinsic::amdgcn_rcp_legacy:6069    case Intrinsic::amdgcn_rsq_legacy:6070    case Intrinsic::amdgcn_rsq_clamp:6071    case Intrinsic::amdgcn_tanh: {6072      if (SNaN)6073        return true;6074 6075      // TODO: Need is known positive check.6076      return false;6077    }6078    case Intrinsic::amdgcn_trig_preop:6079    case Intrinsic::amdgcn_fdot2:6080      // TODO: Refine on operand6081      return SNaN;6082    case Intrinsic::amdgcn_fma_legacy:6083      if (SNaN)6084        return true;6085      return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&6086             DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1) &&6087             DAG.isKnownNeverNaN(Op.getOperand(3), SNaN, Depth + 1);6088    default:6089      return false;6090    }6091  }6092  default:6093    return false;6094  }6095}6096 6097bool AMDGPUTargetLowering::isReassocProfitable(MachineRegisterInfo &MRI,6098                                               Register N0, Register N1) const {6099  return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks6100}6101