brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.0 KiB · a7c25b2 Raw
439 lines · cpp
1//===------ SystemZ.cpp - Emit LLVM Code for builtins ---------------------===//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// This contains code to emit Builtin calls as LLVM code.10//11//===----------------------------------------------------------------------===//12 13#include "CodeGenFunction.h"14#include "clang/Basic/TargetBuiltins.h"15#include "llvm/IR/IntrinsicsS390.h"16 17using namespace clang;18using namespace CodeGen;19using namespace llvm;20 21/// Handle a SystemZ function in which the final argument is a pointer22/// to an int that receives the post-instruction CC value.  At the LLVM level23/// this is represented as a function that returns a {result, cc} pair.24static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction &CGF,25                                         unsigned IntrinsicID,26                                         const CallExpr *E) {27  unsigned NumArgs = E->getNumArgs() - 1;28  SmallVector<Value *, 8> Args(NumArgs);29  for (unsigned I = 0; I < NumArgs; ++I)30    Args[I] = CGF.EmitScalarExpr(E->getArg(I));31  Address CCPtr = CGF.EmitPointerWithAlignment(E->getArg(NumArgs));32  Function *F = CGF.CGM.getIntrinsic(IntrinsicID);33  Value *Call = CGF.Builder.CreateCall(F, Args);34  Value *CC = CGF.Builder.CreateExtractValue(Call, 1);35  CGF.Builder.CreateStore(CC, CCPtr);36  return CGF.Builder.CreateExtractValue(Call, 0);37}38 39Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,40                                               const CallExpr *E) {41  switch (BuiltinID) {42  case SystemZ::BI__builtin_tbegin: {43    Value *TDB = EmitScalarExpr(E->getArg(0));44    Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);45    Function *F = CGM.getIntrinsic(Intrinsic::s390_tbegin);46    return Builder.CreateCall(F, {TDB, Control});47  }48  case SystemZ::BI__builtin_tbegin_nofloat: {49    Value *TDB = EmitScalarExpr(E->getArg(0));50    Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);51    Function *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat);52    return Builder.CreateCall(F, {TDB, Control});53  }54  case SystemZ::BI__builtin_tbeginc: {55    Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy);56    Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08);57    Function *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc);58    return Builder.CreateCall(F, {TDB, Control});59  }60  case SystemZ::BI__builtin_tabort: {61    Value *Data = EmitScalarExpr(E->getArg(0));62    Function *F = CGM.getIntrinsic(Intrinsic::s390_tabort);63    return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort"));64  }65  case SystemZ::BI__builtin_non_tx_store: {66    Value *Address = EmitScalarExpr(E->getArg(0));67    Value *Data = EmitScalarExpr(E->getArg(1));68    Function *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);69    return Builder.CreateCall(F, {Data, Address});70  }71 72  // Vector builtins.  Note that most vector builtins are mapped automatically73  // to target-specific LLVM intrinsics.  The ones handled specially here can74  // be represented via standard LLVM IR, which is preferable to enable common75  // LLVM optimizations.76 77  case SystemZ::BI__builtin_s390_vclzb:78  case SystemZ::BI__builtin_s390_vclzh:79  case SystemZ::BI__builtin_s390_vclzf:80  case SystemZ::BI__builtin_s390_vclzg:81  case SystemZ::BI__builtin_s390_vclzq: {82    llvm::Type *ResultType = ConvertType(E->getType());83    Value *X = EmitScalarExpr(E->getArg(0));84    Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);85    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);86    return Builder.CreateCall(F, {X, Undef});87  }88 89  case SystemZ::BI__builtin_s390_vctzb:90  case SystemZ::BI__builtin_s390_vctzh:91  case SystemZ::BI__builtin_s390_vctzf:92  case SystemZ::BI__builtin_s390_vctzg:93  case SystemZ::BI__builtin_s390_vctzq: {94    llvm::Type *ResultType = ConvertType(E->getType());95    Value *X = EmitScalarExpr(E->getArg(0));96    Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);97    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);98    return Builder.CreateCall(F, {X, Undef});99  }100 101  case SystemZ::BI__builtin_s390_verllb:102  case SystemZ::BI__builtin_s390_verllh:103  case SystemZ::BI__builtin_s390_verllf:104  case SystemZ::BI__builtin_s390_verllg: {105    llvm::Type *ResultType = ConvertType(E->getType());106    llvm::Value *Src = EmitScalarExpr(E->getArg(0));107    llvm::Value *Amt = EmitScalarExpr(E->getArg(1));108    // Splat scalar rotate amount to vector type.109    unsigned NumElts = cast<llvm::FixedVectorType>(ResultType)->getNumElements();110    Amt = Builder.CreateIntCast(Amt, ResultType->getScalarType(), false);111    Amt = Builder.CreateVectorSplat(NumElts, Amt);112    Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);113    return Builder.CreateCall(F, { Src, Src, Amt });114  }115 116  case SystemZ::BI__builtin_s390_verllvb:117  case SystemZ::BI__builtin_s390_verllvh:118  case SystemZ::BI__builtin_s390_verllvf:119  case SystemZ::BI__builtin_s390_verllvg: {120    llvm::Type *ResultType = ConvertType(E->getType());121    llvm::Value *Src = EmitScalarExpr(E->getArg(0));122    llvm::Value *Amt = EmitScalarExpr(E->getArg(1));123    Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);124    return Builder.CreateCall(F, { Src, Src, Amt });125  }126 127  case SystemZ::BI__builtin_s390_vfsqsb:128  case SystemZ::BI__builtin_s390_vfsqdb: {129    llvm::Type *ResultType = ConvertType(E->getType());130    Value *X = EmitScalarExpr(E->getArg(0));131    if (Builder.getIsFPConstrained()) {132      Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt, ResultType);133      return Builder.CreateConstrainedFPCall(F, { X });134    } else {135      Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);136      return Builder.CreateCall(F, X);137    }138  }139  case SystemZ::BI__builtin_s390_vfmasb:140  case SystemZ::BI__builtin_s390_vfmadb: {141    llvm::Type *ResultType = ConvertType(E->getType());142    Value *X = EmitScalarExpr(E->getArg(0));143    Value *Y = EmitScalarExpr(E->getArg(1));144    Value *Z = EmitScalarExpr(E->getArg(2));145    if (Builder.getIsFPConstrained()) {146      Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);147      return Builder.CreateConstrainedFPCall(F, {X, Y, Z});148    } else {149      Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);150      return Builder.CreateCall(F, {X, Y, Z});151    }152  }153  case SystemZ::BI__builtin_s390_vfmssb:154  case SystemZ::BI__builtin_s390_vfmsdb: {155    llvm::Type *ResultType = ConvertType(E->getType());156    Value *X = EmitScalarExpr(E->getArg(0));157    Value *Y = EmitScalarExpr(E->getArg(1));158    Value *Z = EmitScalarExpr(E->getArg(2));159    if (Builder.getIsFPConstrained()) {160      Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);161      return Builder.CreateConstrainedFPCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});162    } else {163      Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);164      return Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});165    }166  }167  case SystemZ::BI__builtin_s390_vfnmasb:168  case SystemZ::BI__builtin_s390_vfnmadb: {169    llvm::Type *ResultType = ConvertType(E->getType());170    Value *X = EmitScalarExpr(E->getArg(0));171    Value *Y = EmitScalarExpr(E->getArg(1));172    Value *Z = EmitScalarExpr(E->getArg(2));173    if (Builder.getIsFPConstrained()) {174      Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);175      return Builder.CreateFNeg(Builder.CreateConstrainedFPCall(F, {X, Y,  Z}), "neg");176    } else {177      Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);178      return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, Z}), "neg");179    }180  }181  case SystemZ::BI__builtin_s390_vfnmssb:182  case SystemZ::BI__builtin_s390_vfnmsdb: {183    llvm::Type *ResultType = ConvertType(E->getType());184    Value *X = EmitScalarExpr(E->getArg(0));185    Value *Y = EmitScalarExpr(E->getArg(1));186    Value *Z = EmitScalarExpr(E->getArg(2));187    if (Builder.getIsFPConstrained()) {188      Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);189      Value *NegZ = Builder.CreateFNeg(Z, "sub");190      return Builder.CreateFNeg(Builder.CreateConstrainedFPCall(F, {X, Y, NegZ}));191    } else {192      Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);193      Value *NegZ = Builder.CreateFNeg(Z, "neg");194      return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, NegZ}));195    }196  }197  case SystemZ::BI__builtin_s390_vflpsb:198  case SystemZ::BI__builtin_s390_vflpdb: {199    llvm::Type *ResultType = ConvertType(E->getType());200    Value *X = EmitScalarExpr(E->getArg(0));201    Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);202    return Builder.CreateCall(F, X);203  }204  case SystemZ::BI__builtin_s390_vflnsb:205  case SystemZ::BI__builtin_s390_vflndb: {206    llvm::Type *ResultType = ConvertType(E->getType());207    Value *X = EmitScalarExpr(E->getArg(0));208    Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);209    return Builder.CreateFNeg(Builder.CreateCall(F, X), "neg");210  }211  case SystemZ::BI__builtin_s390_vfisb:212  case SystemZ::BI__builtin_s390_vfidb: {213    llvm::Type *ResultType = ConvertType(E->getType());214    Value *X = EmitScalarExpr(E->getArg(0));215    // Constant-fold the M4 and M5 mask arguments.216    llvm::APSInt M4 = *E->getArg(1)->getIntegerConstantExpr(getContext());217    llvm::APSInt M5 = *E->getArg(2)->getIntegerConstantExpr(getContext());218    // Check whether this instance can be represented via a LLVM standard219    // intrinsic.  We only support some combinations of M4 and M5.220    Intrinsic::ID ID = Intrinsic::not_intrinsic;221    Intrinsic::ID CI;222    switch (M4.getZExtValue()) {223    default: break;224    case 0:  // IEEE-inexact exception allowed225      switch (M5.getZExtValue()) {226      default: break;227      case 0: ID = Intrinsic::rint;228              CI = Intrinsic::experimental_constrained_rint; break;229      }230      break;231    case 4:  // IEEE-inexact exception suppressed232      switch (M5.getZExtValue()) {233      default: break;234      case 0: ID = Intrinsic::nearbyint;235              CI = Intrinsic::experimental_constrained_nearbyint; break;236      case 1: ID = Intrinsic::round;237              CI = Intrinsic::experimental_constrained_round; break;238      case 4: ID = Intrinsic::roundeven;239              CI = Intrinsic::experimental_constrained_roundeven; break;240      case 5: ID = Intrinsic::trunc;241              CI = Intrinsic::experimental_constrained_trunc; break;242      case 6: ID = Intrinsic::ceil;243              CI = Intrinsic::experimental_constrained_ceil; break;244      case 7: ID = Intrinsic::floor;245              CI = Intrinsic::experimental_constrained_floor; break;246      }247      break;248    }249    if (ID != Intrinsic::not_intrinsic) {250      if (Builder.getIsFPConstrained()) {251        Function *F = CGM.getIntrinsic(CI, ResultType);252        return Builder.CreateConstrainedFPCall(F, X);253      } else {254        Function *F = CGM.getIntrinsic(ID, ResultType);255        return Builder.CreateCall(F, X);256      }257    }258    switch (BuiltinID) { // FIXME: constrained version?259      case SystemZ::BI__builtin_s390_vfisb: ID = Intrinsic::s390_vfisb; break;260      case SystemZ::BI__builtin_s390_vfidb: ID = Intrinsic::s390_vfidb; break;261      default: llvm_unreachable("Unknown BuiltinID");262    }263    Function *F = CGM.getIntrinsic(ID);264    Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);265    Value *M5Value = llvm::ConstantInt::get(getLLVMContext(), M5);266    return Builder.CreateCall(F, {X, M4Value, M5Value});267  }268  case SystemZ::BI__builtin_s390_vfmaxsb:269  case SystemZ::BI__builtin_s390_vfmaxdb: {270    llvm::Type *ResultType = ConvertType(E->getType());271    Value *X = EmitScalarExpr(E->getArg(0));272    Value *Y = EmitScalarExpr(E->getArg(1));273    // Constant-fold the M4 mask argument.274    llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext());275    // Check whether this instance can be represented via a LLVM standard276    // intrinsic.  We only support some values of M4.277    Intrinsic::ID ID = Intrinsic::not_intrinsic;278    Intrinsic::ID CI;279    switch (M4.getZExtValue()) {280    default: break;281    case 4: ID = Intrinsic::maxnum;282            CI = Intrinsic::experimental_constrained_maxnum; break;283    }284    if (ID != Intrinsic::not_intrinsic) {285      if (Builder.getIsFPConstrained()) {286        Function *F = CGM.getIntrinsic(CI, ResultType);287        return Builder.CreateConstrainedFPCall(F, {X, Y});288      } else {289        Function *F = CGM.getIntrinsic(ID, ResultType);290        return Builder.CreateCall(F, {X, Y});291      }292    }293    switch (BuiltinID) {294      case SystemZ::BI__builtin_s390_vfmaxsb: ID = Intrinsic::s390_vfmaxsb; break;295      case SystemZ::BI__builtin_s390_vfmaxdb: ID = Intrinsic::s390_vfmaxdb; break;296      default: llvm_unreachable("Unknown BuiltinID");297    }298    Function *F = CGM.getIntrinsic(ID);299    Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);300    return Builder.CreateCall(F, {X, Y, M4Value});301  }302  case SystemZ::BI__builtin_s390_vfminsb:303  case SystemZ::BI__builtin_s390_vfmindb: {304    llvm::Type *ResultType = ConvertType(E->getType());305    Value *X = EmitScalarExpr(E->getArg(0));306    Value *Y = EmitScalarExpr(E->getArg(1));307    // Constant-fold the M4 mask argument.308    llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext());309    // Check whether this instance can be represented via a LLVM standard310    // intrinsic.  We only support some values of M4.311    Intrinsic::ID ID = Intrinsic::not_intrinsic;312    Intrinsic::ID CI;313    switch (M4.getZExtValue()) {314    default: break;315    case 4: ID = Intrinsic::minnum;316            CI = Intrinsic::experimental_constrained_minnum; break;317    }318    if (ID != Intrinsic::not_intrinsic) {319      if (Builder.getIsFPConstrained()) {320        Function *F = CGM.getIntrinsic(CI, ResultType);321        return Builder.CreateConstrainedFPCall(F, {X, Y});322      } else {323        Function *F = CGM.getIntrinsic(ID, ResultType);324        return Builder.CreateCall(F, {X, Y});325      }326    }327    switch (BuiltinID) {328      case SystemZ::BI__builtin_s390_vfminsb: ID = Intrinsic::s390_vfminsb; break;329      case SystemZ::BI__builtin_s390_vfmindb: ID = Intrinsic::s390_vfmindb; break;330      default: llvm_unreachable("Unknown BuiltinID");331    }332    Function *F = CGM.getIntrinsic(ID);333    Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);334    return Builder.CreateCall(F, {X, Y, M4Value});335  }336 337  case SystemZ::BI__builtin_s390_vlbrh:338  case SystemZ::BI__builtin_s390_vlbrf:339  case SystemZ::BI__builtin_s390_vlbrg:340  case SystemZ::BI__builtin_s390_vlbrq: {341    llvm::Type *ResultType = ConvertType(E->getType());342    Value *X = EmitScalarExpr(E->getArg(0));343    Function *F = CGM.getIntrinsic(Intrinsic::bswap, ResultType);344    return Builder.CreateCall(F, X);345  }346 347  // Vector intrinsics that output the post-instruction CC value.348 349#define INTRINSIC_WITH_CC(NAME) \350    case SystemZ::BI__builtin_##NAME: \351      return EmitSystemZIntrinsicWithCC(*this, Intrinsic::NAME, E)352 353  INTRINSIC_WITH_CC(s390_vpkshs);354  INTRINSIC_WITH_CC(s390_vpksfs);355  INTRINSIC_WITH_CC(s390_vpksgs);356 357  INTRINSIC_WITH_CC(s390_vpklshs);358  INTRINSIC_WITH_CC(s390_vpklsfs);359  INTRINSIC_WITH_CC(s390_vpklsgs);360 361  INTRINSIC_WITH_CC(s390_vceqbs);362  INTRINSIC_WITH_CC(s390_vceqhs);363  INTRINSIC_WITH_CC(s390_vceqfs);364  INTRINSIC_WITH_CC(s390_vceqgs);365  INTRINSIC_WITH_CC(s390_vceqqs);366 367  INTRINSIC_WITH_CC(s390_vchbs);368  INTRINSIC_WITH_CC(s390_vchhs);369  INTRINSIC_WITH_CC(s390_vchfs);370  INTRINSIC_WITH_CC(s390_vchgs);371  INTRINSIC_WITH_CC(s390_vchqs);372 373  INTRINSIC_WITH_CC(s390_vchlbs);374  INTRINSIC_WITH_CC(s390_vchlhs);375  INTRINSIC_WITH_CC(s390_vchlfs);376  INTRINSIC_WITH_CC(s390_vchlgs);377  INTRINSIC_WITH_CC(s390_vchlqs);378 379  INTRINSIC_WITH_CC(s390_vfaebs);380  INTRINSIC_WITH_CC(s390_vfaehs);381  INTRINSIC_WITH_CC(s390_vfaefs);382 383  INTRINSIC_WITH_CC(s390_vfaezbs);384  INTRINSIC_WITH_CC(s390_vfaezhs);385  INTRINSIC_WITH_CC(s390_vfaezfs);386 387  INTRINSIC_WITH_CC(s390_vfeebs);388  INTRINSIC_WITH_CC(s390_vfeehs);389  INTRINSIC_WITH_CC(s390_vfeefs);390 391  INTRINSIC_WITH_CC(s390_vfeezbs);392  INTRINSIC_WITH_CC(s390_vfeezhs);393  INTRINSIC_WITH_CC(s390_vfeezfs);394 395  INTRINSIC_WITH_CC(s390_vfenebs);396  INTRINSIC_WITH_CC(s390_vfenehs);397  INTRINSIC_WITH_CC(s390_vfenefs);398 399  INTRINSIC_WITH_CC(s390_vfenezbs);400  INTRINSIC_WITH_CC(s390_vfenezhs);401  INTRINSIC_WITH_CC(s390_vfenezfs);402 403  INTRINSIC_WITH_CC(s390_vistrbs);404  INTRINSIC_WITH_CC(s390_vistrhs);405  INTRINSIC_WITH_CC(s390_vistrfs);406 407  INTRINSIC_WITH_CC(s390_vstrcbs);408  INTRINSIC_WITH_CC(s390_vstrchs);409  INTRINSIC_WITH_CC(s390_vstrcfs);410 411  INTRINSIC_WITH_CC(s390_vstrczbs);412  INTRINSIC_WITH_CC(s390_vstrczhs);413  INTRINSIC_WITH_CC(s390_vstrczfs);414 415  INTRINSIC_WITH_CC(s390_vfcesbs);416  INTRINSIC_WITH_CC(s390_vfcedbs);417  INTRINSIC_WITH_CC(s390_vfchsbs);418  INTRINSIC_WITH_CC(s390_vfchdbs);419  INTRINSIC_WITH_CC(s390_vfchesbs);420  INTRINSIC_WITH_CC(s390_vfchedbs);421 422  INTRINSIC_WITH_CC(s390_vftcisb);423  INTRINSIC_WITH_CC(s390_vftcidb);424 425  INTRINSIC_WITH_CC(s390_vstrsb);426  INTRINSIC_WITH_CC(s390_vstrsh);427  INTRINSIC_WITH_CC(s390_vstrsf);428 429  INTRINSIC_WITH_CC(s390_vstrszb);430  INTRINSIC_WITH_CC(s390_vstrszh);431  INTRINSIC_WITH_CC(s390_vstrszf);432 433#undef INTRINSIC_WITH_CC434 435  default:436    return nullptr;437  }438}439