// Copyright (c) 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SOURCE_FUZZ_TRANSFORMATION_FLATTEN_CONDITIONAL_BRANCH_H_
#define SOURCE_FUZZ_TRANSFORMATION_FLATTEN_CONDITIONAL_BRANCH_H_

#include "source/fuzz/transformation.h"

namespace spvtools {
namespace fuzz {

class TransformationFlattenConditionalBranch : public Transformation {
 public:
  explicit TransformationFlattenConditionalBranch(
      const protobufs::TransformationFlattenConditionalBranch& message);

  TransformationFlattenConditionalBranch(
      uint32_t header_block_id, bool true_branch_first,
      uint32_t fresh_id_for_bvec2_selector,
      uint32_t fresh_id_for_bvec3_selector,
      uint32_t fresh_id_for_bvec4_selector,
      const std::vector<protobufs::SideEffectWrapperInfo>&
          side_effect_wrappers_info);

  // - |message_.header_block_id| must be the label id of a reachable selection
  //   header, which ends with an OpBranchConditional instruction.
  // - The condition of the OpBranchConditional instruction must not be an
  //   irrelevant id.
  // - The header block and the merge block must describe a single-entry,
  //   single-exit region.
  // - The region must not contain barrier or OpSampledImage instructions.
  // - The region must not contain selection or loop constructs.
  // - The region must not define ids that are the base objects for existing
  //   synonym facts.
  // - For each instruction that requires additional fresh ids, then:
  //   - if the instruction is mapped to the required ids for enclosing it by
  //     |message_.side_effect_wrapper_info|, these must be valid (the
  //     fresh ids must be non-zero, fresh and distinct);
  //   - if there is no such mapping, the transformation context must have
  //     overflow ids available.
  bool IsApplicable(
      opt::IRContext* ir_context,
      const TransformationContext& transformation_context) const override;

  // Flattens the selection construct with header |message_.header_block_id|,
  // changing any OpPhi in the block where the flow converges to OpSelect and
  // enclosing any instruction with side effects in conditionals so that
  // they are only executed when they should.
  void Apply(opt::IRContext* ir_context,
             TransformationContext* transformation_context) const override;

  std::unordered_set<uint32_t> GetFreshIds() const override;

  protobufs::Transformation ToMessage() const override;

  // Returns true if the conditional headed by |header| can be flattened,
  // according to the conditions of the IsApplicable method, assuming that
  // enough fresh ids would be provided. In this case, it fills the
  // |instructions_that_need_ids| set with all the instructions that would
  // require fresh ids.
  // Returns false otherwise.
  // Assumes that |header| is the header of a conditional, so its last two
  // instructions are OpSelectionMerge and OpBranchConditional.
  static bool GetProblematicInstructionsIfConditionalCanBeFlattened(
      opt::IRContext* ir_context, opt::BasicBlock* header,
      const TransformationContext& transformation_context,
      std::set<opt::Instruction*>* instructions_that_need_ids);

  // Returns true iff the given instruction needs a placeholder to be enclosed
  // inside a conditional. So, it returns:
  // - true if the instruction has a non-void result id,
  // - false if the instruction does not have a result id or has a void result
  //   id.
  // Assumes that the instruction has side effects, requiring it to be enclosed
  // inside a conditional, and that it can be enclosed inside a conditional
  // keeping the module valid. Assumes that, if the instruction has a void
  // result type, its result id is not used in the module.
  static bool InstructionNeedsPlaceholder(opt::IRContext* ir_context,
                                          const opt::Instruction& instruction);

  // Returns true if and only if the SPIR-V version is such that the arguments
  // to OpSelect are restricted to only scalars, pointers (if the appropriate
  // capability is enabled) and component-wise vectors.
  static bool OpSelectArgumentsAreRestricted(opt::IRContext* ir_context);

  // Find the first block where flow converges (it is not necessarily the merge
  // block) by walking the true branch until reaching a block that post-
  // dominates the header.
  // This is necessary because a potential common set of blocks at the end of
  // the construct should not be duplicated.
  static uint32_t FindConvergenceBlock(opt::IRContext* ir_context,
                                       const opt::BasicBlock& header_block);

 private:
  // Returns an unordered_map mapping instructions to the info required to
  // enclose them inside a conditional. It maps the instructions to the
  // corresponding entry in |message_.side_effect_wrapper_info|.
  std::unordered_map<opt::Instruction*, protobufs::SideEffectWrapperInfo>
  GetInstructionsToWrapperInfo(opt::IRContext* ir_context) const;

  // Splits the given block, adding a new selection construct so that the given
  // instruction is only executed if the boolean value of |condition_id| matches
  // the value of |exec_if_cond_true|.
  // Assumes that all parameters are consistent.
  // 2 fresh ids are required if the instruction does not have a result id (the
  // first two ids in |wrapper_info| must be valid fresh ids), 5 otherwise.
  // Returns the merge block created.
  //
  // |dead_blocks| and |irrelevant_ids| are used to record the ids of blocks
  // and instructions for which dead block and irrelevant id facts should
  // ultimately be created.
  static opt::BasicBlock* EncloseInstructionInConditional(
      opt::IRContext* ir_context,
      const TransformationContext& transformation_context,
      opt::BasicBlock* block, opt::Instruction* instruction,
      const protobufs::SideEffectWrapperInfo& wrapper_info,
      uint32_t condition_id, bool exec_if_cond_true,
      std::vector<uint32_t>* dead_blocks,
      std::vector<uint32_t>* irrelevant_ids);

  // Turns every OpPhi instruction of |convergence_block| -- the convergence
  // block for |header_block| (both in |ir_context|) into an OpSelect
  // instruction.
  void RewriteOpPhiInstructionsAtConvergenceBlock(
      const opt::BasicBlock& header_block, uint32_t convergence_block_id,
      opt::IRContext* ir_context) const;

  // Adds an OpCompositeExtract instruction to the start of |block| in
  // |ir_context|, with result id given by |fresh_id|.  The instruction will
  // make a |dimension|-dimensional boolean vector with
  // |branch_condition_operand| at every component.
  static void AddBooleanVectorConstructorToBlock(
      uint32_t fresh_id, uint32_t dimension,
      const opt::Operand& branch_condition_operand, opt::IRContext* ir_context,
      opt::BasicBlock* block);

  // Returns true if the given instruction either has no side effects or it can
  // be handled by being enclosed in a conditional.
  static bool InstructionCanBeHandled(opt::IRContext* ir_context,
                                      const opt::Instruction& instruction);

  protobufs::TransformationFlattenConditionalBranch message_;
};

}  // namespace fuzz
}  // namespace spvtools

#endif  // SOURCE_FUZZ_TRANSFORMATION_FLATTEN_CONDITIONAL_BRANCH_H_
