Repository: llvm/llvm-project
File: llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (C++)

Code before:
            : BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
                  .addDef(NewReg)
                  .addUse(GR.getSPIRVTypeID(SpvI32Ty))
                  .addImm(APInt(32, Val).getZExtValue());
    constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
    GR.add(ConstInt, MI);
  }
  return NewReg;
}

bool SPIRVInstructionSelector::selectFCmp(Register ResVReg,
                                          SPIRVTypeInst ResType,
                                          MachineInstr &I) const {
  unsigned CmpOp = getFCmpOpcode(I.getOperand(1).getPredicate());
  return selectCmp(ResVReg, ResType, CmpOp, I);
}

bool SPIRVInstructionSelector::selectExp10(Register ResVReg,
                                           SPIRVTypeInst ResType,
                                           MachineInstr &I) const {

  if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
    return selectExtInst(ResVReg, ResType, I, CL::exp10);
  } else if (STI.canUseExtInstSet(SPIRV::InstructionSet::GLSL_std_450)) {
    /// There is no exp10 in GLSL. Use exp10(x) = exp2(x * log2(10)) instead
    /// log2(10) ~= 3.3219280948874

    if (ResType->getOpcode() != SPIRV::OpTypeVector &&
        ResType->getOpcode() != SPIRV::OpTypeFloat)
      return false;

    MachineIRBuilder MIRBuilder(I);

    SPIRVTypeInst SpirvScalarType = ResType->getOpcode() == SPIRV::OpTypeVector
                                        ? SPIRVTypeInst(GR.getSPIRVTypeForVReg(
                                              ResType->getOperand(1).getReg()))
                                        : ResType;

    Register ConstReg = GR.buildConstantFP(APFloat(3.3219280948874f),
                                           MIRBuilder, SpirvScalarType);
    Register ArgReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
    auto Opcode = ResType->getOpcode() == SPIRV::OpTypeVector
                      ? SPIRV::OpVectorTimesScalar
                      : SPIRV::OpFMulS;

    if (!selectOpWithSrcs(
            ArgReg, ResType, I,
            std::vector<Register>({ConstReg, I.getOperand(1).getReg()}),
            Opcode))
      return false;
    return selectExtInstWithSrcs(ResVReg, ResType, I,

Review comment (suggestion):
I'm not familiar with GLSL. Do you have a reference that suggests this transformation is equivalent? Otherwise we may have to restrict this for some fast-math flags.

Code after:
    return false;

  auto IsZero = [this](Register Reg) {
    MachineInstr *Def = getDefInstrMaybeConstant(Reg, MRI);
    if (!Def)
      return false;

    if (Def->getOpcode() == SPIRV::OpConstantNull)
      return true;

    if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
        Def->getOpcode() == SPIRV::OpConstantI)
      return getIConstVal(Reg, MRI) == 0;

    return false;
  };

  if (IsZero(Reg))
    return true;

  MachineInstr *Def = MRI->getVRegDef(Reg);
  if (!Def)
    return false;

  if (Def->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
      (Def->getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
       cast<GIntrinsic>(Def)->getIntrinsicID() ==
           Intrinsic::spv_const_composite)) {
    unsigned StartOp = Def->getOpcode() == TargetOpcode::G_BUILD_VECTOR ? 1 : 2;
    for (unsigned i = StartOp; i < Def->getNumOperands(); ++i) {
      if (!IsZero(Def->getOperand(i).getReg()))
        return false;
    }
    return true;
  }

  return false;
}

Register SPIRVInstructionSelector::buildZerosValF(SPIRVTypeInst ResType,
                                                  MachineInstr &I) const {
  // OpenCL uses nulls for Zero. In HLSL we don't use null constants.
  bool ZeroAsNull = !STI.isShader();
  APFloat VZero = getZeroFP(GR.getTypeForSPIRVType(ResType));
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    return GR.getOrCreateConstVector(VZero, I, ResType, TII, ZeroAsNull);
  return GR.getOrCreateConstFP(VZero, I, ResType, TII, ZeroAsNull);
}

Register SPIRVInstructionSelector::buildOnesValF(SPIRVTypeInst ResType,
                                                 MachineInstr &I) const {