diff options
Diffstat (limited to 'source/opt/fold.cpp')
-rw-r--r-- | source/opt/fold.cpp | 207 |
1 files changed, 104 insertions, 103 deletions
diff --git a/source/opt/fold.cpp b/source/opt/fold.cpp index 315741ad7..3c234c4e3 100644 --- a/source/opt/fold.cpp +++ b/source/opt/fold.cpp @@ -42,23 +42,24 @@ namespace { } // namespace -uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const { +uint32_t InstructionFolder::UnaryOperate(spv::Op opcode, + uint32_t operand) const { switch (opcode) { // Arthimetics - case SpvOp::SpvOpSNegate: { + case spv::Op::OpSNegate: { int32_t s_operand = static_cast<int32_t>(operand); if (s_operand == std::numeric_limits<int32_t>::min()) { return s_operand; } return -s_operand; } - case SpvOp::SpvOpNot: + case spv::Op::OpNot: return ~operand; - case SpvOp::SpvOpLogicalNot: + case spv::Op::OpLogicalNot: return !static_cast<bool>(operand); - case SpvOp::SpvOpUConvert: + case spv::Op::OpUConvert: return operand; - case SpvOp::SpvOpSConvert: + case spv::Op::OpSConvert: return operand; default: assert(false && @@ -67,31 +68,31 @@ uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const { } } -uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, +uint32_t InstructionFolder::BinaryOperate(spv::Op opcode, uint32_t a, uint32_t b) const { switch (opcode) { // Arthimetics - case SpvOp::SpvOpIAdd: + case spv::Op::OpIAdd: return a + b; - case SpvOp::SpvOpISub: + case spv::Op::OpISub: return a - b; - case SpvOp::SpvOpIMul: + case spv::Op::OpIMul: return a * b; - case SpvOp::SpvOpUDiv: + case spv::Op::OpUDiv: if (b != 0) { return a / b; } else { // Dividing by 0 is undefined, so we will just pick 0. return 0; } - case SpvOp::SpvOpSDiv: + case spv::Op::OpSDiv: if (b != 0u) { return (static_cast<int32_t>(a)) / (static_cast<int32_t>(b)); } else { // Dividing by 0 is undefined, so we will just pick 0. return 0; } - case SpvOp::SpvOpSRem: { + case spv::Op::OpSRem: { // The sign of non-zero result comes from the first operand: a. This is // guaranteed by C++11 rules for integer division operator. The division // result is rounded toward zero, so the result of '%' has the sign of @@ -103,10 +104,10 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, return 0; } } - case SpvOp::SpvOpSMod: { + case spv::Op::OpSMod: { // The sign of non-zero result comes from the second operand: b if (b != 0u) { - int32_t rem = BinaryOperate(SpvOp::SpvOpSRem, a, b); + int32_t rem = BinaryOperate(spv::Op::OpSRem, a, b); int32_t b_prim = static_cast<int32_t>(b); return (rem + b_prim) % b_prim; } else { @@ -114,7 +115,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, return 0; } } - case SpvOp::SpvOpUMod: + case spv::Op::OpUMod: if (b != 0u) { return (a % b); } else { @@ -123,7 +124,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, } // Shifting - case SpvOp::SpvOpShiftRightLogical: + case spv::Op::OpShiftRightLogical: if (b >= 32) { // This is undefined behaviour when |b| > 32. Choose 0 for consistency. // When |b| == 32, doing the shift in C++ in undefined, but the result @@ -131,7 +132,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, return 0; } return a >> b; - case SpvOp::SpvOpShiftRightArithmetic: + case spv::Op::OpShiftRightArithmetic: if (b > 32) { // This is undefined behaviour. Choose 0 for consistency. return 0; @@ -146,7 +147,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, } } return (static_cast<int32_t>(a)) >> b; - case SpvOp::SpvOpShiftLeftLogical: + case spv::Op::OpShiftLeftLogical: if (b >= 32) { // This is undefined behaviour when |b| > 32. Choose 0 for consistency. // When |b| == 32, doing the shift in C++ in undefined, but the result @@ -156,43 +157,43 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, return a << b; // Bitwise operations - case SpvOp::SpvOpBitwiseOr: + case spv::Op::OpBitwiseOr: return a | b; - case SpvOp::SpvOpBitwiseAnd: + case spv::Op::OpBitwiseAnd: return a & b; - case SpvOp::SpvOpBitwiseXor: + case spv::Op::OpBitwiseXor: return a ^ b; // Logical - case SpvOp::SpvOpLogicalEqual: + case spv::Op::OpLogicalEqual: return (static_cast<bool>(a)) == (static_cast<bool>(b)); - case SpvOp::SpvOpLogicalNotEqual: + case spv::Op::OpLogicalNotEqual: return (static_cast<bool>(a)) != (static_cast<bool>(b)); - case SpvOp::SpvOpLogicalOr: + case spv::Op::OpLogicalOr: return (static_cast<bool>(a)) || (static_cast<bool>(b)); - case SpvOp::SpvOpLogicalAnd: + case spv::Op::OpLogicalAnd: return (static_cast<bool>(a)) && (static_cast<bool>(b)); // Comparison - case SpvOp::SpvOpIEqual: + case spv::Op::OpIEqual: return a == b; - case SpvOp::SpvOpINotEqual: + case spv::Op::OpINotEqual: return a != b; - case SpvOp::SpvOpULessThan: + case spv::Op::OpULessThan: return a < b; - case SpvOp::SpvOpSLessThan: + case spv::Op::OpSLessThan: return (static_cast<int32_t>(a)) < (static_cast<int32_t>(b)); - case SpvOp::SpvOpUGreaterThan: + case spv::Op::OpUGreaterThan: return a > b; - case SpvOp::SpvOpSGreaterThan: + case spv::Op::OpSGreaterThan: return (static_cast<int32_t>(a)) > (static_cast<int32_t>(b)); - case SpvOp::SpvOpULessThanEqual: + case spv::Op::OpULessThanEqual: return a <= b; - case SpvOp::SpvOpSLessThanEqual: + case spv::Op::OpSLessThanEqual: return (static_cast<int32_t>(a)) <= (static_cast<int32_t>(b)); - case SpvOp::SpvOpUGreaterThanEqual: + case spv::Op::OpUGreaterThanEqual: return a >= b; - case SpvOp::SpvOpSGreaterThanEqual: + case spv::Op::OpSGreaterThanEqual: return (static_cast<int32_t>(a)) >= (static_cast<int32_t>(b)); default: assert(false && @@ -201,10 +202,10 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a, } } -uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b, - uint32_t c) const { +uint32_t InstructionFolder::TernaryOperate(spv::Op opcode, uint32_t a, + uint32_t b, uint32_t c) const { switch (opcode) { - case SpvOp::SpvOpSelect: + case spv::Op::OpSelect: return (static_cast<bool>(a)) ? b : c; default: assert(false && @@ -214,7 +215,7 @@ uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b, } uint32_t InstructionFolder::OperateWords( - SpvOp opcode, const std::vector<uint32_t>& operand_words) const { + spv::Op opcode, const std::vector<uint32_t>& operand_words) const { switch (operand_words.size()) { case 1: return UnaryOperate(opcode, operand_words.front()); @@ -233,7 +234,7 @@ bool InstructionFolder::FoldInstructionInternal(Instruction* inst) const { auto identity_map = [](uint32_t id) { return id; }; Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map); if (folded_inst != nullptr) { - inst->SetOpcode(SpvOpCopyObject); + inst->SetOpcode(spv::Op::OpCopyObject); inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {folded_inst->result_id()}}}); return true; } @@ -256,7 +257,7 @@ bool InstructionFolder::FoldInstructionInternal(Instruction* inst) const { // result in 32 bit word. Scalar constants with longer than 32-bit width are // not accepted in this function. uint32_t InstructionFolder::FoldScalars( - SpvOp opcode, + spv::Op opcode, const std::vector<const analysis::Constant*>& operands) const { assert(IsFoldableOpcode(opcode) && "Unhandled instruction opcode in FoldScalars"); @@ -282,7 +283,7 @@ uint32_t InstructionFolder::FoldScalars( bool InstructionFolder::FoldBinaryIntegerOpToConstant( Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, uint32_t* result) const { - SpvOp opcode = inst->opcode(); + spv::Op opcode = inst->opcode(); analysis::ConstantManager* const_manger = context_->get_constant_mgr(); uint32_t ids[2]; @@ -300,7 +301,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( switch (opcode) { // Arthimetics - case SpvOp::SpvOpIMul: + case spv::Op::OpIMul: for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr && constants[i]->IsZero()) { *result = 0; @@ -308,11 +309,11 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( } } break; - case SpvOp::SpvOpUDiv: - case SpvOp::SpvOpSDiv: - case SpvOp::SpvOpSRem: - case SpvOp::SpvOpSMod: - case SpvOp::SpvOpUMod: + case spv::Op::OpUDiv: + case spv::Op::OpSDiv: + case spv::Op::OpSRem: + case spv::Op::OpSMod: + case spv::Op::OpUMod: // This changes undefined behaviour (ie divide by 0) into a 0. for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr && constants[i]->IsZero()) { @@ -323,8 +324,8 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( break; // Shifting - case SpvOp::SpvOpShiftRightLogical: - case SpvOp::SpvOpShiftLeftLogical: + case spv::Op::OpShiftRightLogical: + case spv::Op::OpShiftLeftLogical: if (constants[1] != nullptr) { // When shifting by a value larger than the size of the result, the // result is undefined. We are setting the undefined behaviour to a @@ -339,7 +340,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( break; // Bitwise operations - case SpvOp::SpvOpBitwiseOr: + case spv::Op::OpBitwiseOr: for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr) { // TODO: Change the mask against a value based on the bit width of the @@ -353,7 +354,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( } } break; - case SpvOp::SpvOpBitwiseAnd: + case spv::Op::OpBitwiseAnd: for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr) { if (constants[i]->IsZero()) { @@ -365,7 +366,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( break; // Comparison - case SpvOp::SpvOpULessThan: + case spv::Op::OpULessThan: if (constants[0] != nullptr && constants[0]->GetU32BitValue() == UINT32_MAX) { *result = false; @@ -376,7 +377,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpSLessThan: + case spv::Op::OpSLessThan: if (constants[0] != nullptr && constants[0]->GetS32BitValue() == INT32_MAX) { *result = false; @@ -388,7 +389,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpUGreaterThan: + case spv::Op::OpUGreaterThan: if (constants[0] != nullptr && constants[0]->IsZero()) { *result = false; return true; @@ -399,7 +400,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpSGreaterThan: + case spv::Op::OpSGreaterThan: if (constants[0] != nullptr && constants[0]->GetS32BitValue() == INT32_MIN) { *result = false; @@ -411,7 +412,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpULessThanEqual: + case spv::Op::OpULessThanEqual: if (constants[0] != nullptr && constants[0]->IsZero()) { *result = true; return true; @@ -422,7 +423,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpSLessThanEqual: + case spv::Op::OpSLessThanEqual: if (constants[0] != nullptr && constants[0]->GetS32BitValue() == INT32_MIN) { *result = true; @@ -434,7 +435,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpUGreaterThanEqual: + case spv::Op::OpUGreaterThanEqual: if (constants[0] != nullptr && constants[0]->GetU32BitValue() == UINT32_MAX) { *result = true; @@ -445,7 +446,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( return true; } break; - case SpvOp::SpvOpSGreaterThanEqual: + case spv::Op::OpSGreaterThanEqual: if (constants[0] != nullptr && constants[0]->GetS32BitValue() == INT32_MAX) { *result = true; @@ -466,7 +467,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant( bool InstructionFolder::FoldBinaryBooleanOpToConstant( Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map, uint32_t* result) const { - SpvOp opcode = inst->opcode(); + spv::Op opcode = inst->opcode(); analysis::ConstantManager* const_manger = context_->get_constant_mgr(); uint32_t ids[2]; @@ -484,7 +485,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant( switch (opcode) { // Logical - case SpvOp::SpvOpLogicalOr: + case spv::Op::OpLogicalOr: for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr) { if (constants[i]->value()) { @@ -494,7 +495,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant( } } break; - case SpvOp::SpvOpLogicalAnd: + case spv::Op::OpLogicalAnd: for (uint32_t i = 0; i < 2; i++) { if (constants[i] != nullptr) { if (!constants[i]->value()) { @@ -526,7 +527,7 @@ bool InstructionFolder::FoldIntegerOpToConstant( } std::vector<uint32_t> InstructionFolder::FoldVectors( - SpvOp opcode, uint32_t num_dims, + spv::Op opcode, uint32_t num_dims, const std::vector<const analysis::Constant*>& operands) const { assert(IsFoldableOpcode(opcode) && "Unhandled instruction opcode in FoldVectors"); @@ -570,44 +571,44 @@ std::vector<uint32_t> InstructionFolder::FoldVectors( return result; } -bool InstructionFolder::IsFoldableOpcode(SpvOp opcode) const { +bool InstructionFolder::IsFoldableOpcode(spv::Op opcode) const { // NOTE: Extend to more opcodes as new cases are handled in the folder // functions. switch (opcode) { - case SpvOp::SpvOpBitwiseAnd: - case SpvOp::SpvOpBitwiseOr: - case SpvOp::SpvOpBitwiseXor: - case SpvOp::SpvOpIAdd: - case SpvOp::SpvOpIEqual: - case SpvOp::SpvOpIMul: - case SpvOp::SpvOpINotEqual: - case SpvOp::SpvOpISub: - case SpvOp::SpvOpLogicalAnd: - case SpvOp::SpvOpLogicalEqual: - case SpvOp::SpvOpLogicalNot: - case SpvOp::SpvOpLogicalNotEqual: - case SpvOp::SpvOpLogicalOr: - case SpvOp::SpvOpNot: - case SpvOp::SpvOpSDiv: - case SpvOp::SpvOpSelect: - case SpvOp::SpvOpSGreaterThan: - case SpvOp::SpvOpSGreaterThanEqual: - case SpvOp::SpvOpShiftLeftLogical: - case SpvOp::SpvOpShiftRightArithmetic: - case SpvOp::SpvOpShiftRightLogical: - case SpvOp::SpvOpSLessThan: - case SpvOp::SpvOpSLessThanEqual: - case SpvOp::SpvOpSMod: - case SpvOp::SpvOpSNegate: - case SpvOp::SpvOpSRem: - case SpvOp::SpvOpSConvert: - case SpvOp::SpvOpUConvert: - case SpvOp::SpvOpUDiv: - case SpvOp::SpvOpUGreaterThan: - case SpvOp::SpvOpUGreaterThanEqual: - case SpvOp::SpvOpULessThan: - case SpvOp::SpvOpULessThanEqual: - case SpvOp::SpvOpUMod: + case spv::Op::OpBitwiseAnd: + case spv::Op::OpBitwiseOr: + case spv::Op::OpBitwiseXor: + case spv::Op::OpIAdd: + case spv::Op::OpIEqual: + case spv::Op::OpIMul: + case spv::Op::OpINotEqual: + case spv::Op::OpISub: + case spv::Op::OpLogicalAnd: + case spv::Op::OpLogicalEqual: + case spv::Op::OpLogicalNot: + case spv::Op::OpLogicalNotEqual: + case spv::Op::OpLogicalOr: + case spv::Op::OpNot: + case spv::Op::OpSDiv: + case spv::Op::OpSelect: + case spv::Op::OpSGreaterThan: + case spv::Op::OpSGreaterThanEqual: + case spv::Op::OpShiftLeftLogical: + case spv::Op::OpShiftRightArithmetic: + case spv::Op::OpShiftRightLogical: + case spv::Op::OpSLessThan: + case spv::Op::OpSLessThanEqual: + case spv::Op::OpSMod: + case spv::Op::OpSNegate: + case spv::Op::OpSRem: + case spv::Op::OpSConvert: + case spv::Op::OpUConvert: + case spv::Op::OpUDiv: + case spv::Op::OpUGreaterThan: + case spv::Op::OpUGreaterThanEqual: + case spv::Op::OpULessThan: + case spv::Op::OpULessThanEqual: + case spv::Op::OpUMod: return true; default: return false; @@ -685,11 +686,11 @@ Instruction* InstructionFolder::FoldInstructionToConstant( bool InstructionFolder::IsFoldableType(Instruction* type_inst) const { // Support 32-bit integers. - if (type_inst->opcode() == SpvOpTypeInt) { + if (type_inst->opcode() == spv::Op::OpTypeInt) { return type_inst->GetSingleWordInOperand(0) == 32; } // Support booleans. - if (type_inst->opcode() == SpvOpTypeBool) { + if (type_inst->opcode() == spv::Op::OpTypeBool) { return true; } // Nothing else yet. @@ -699,7 +700,7 @@ bool InstructionFolder::IsFoldableType(Instruction* type_inst) const { bool InstructionFolder::FoldInstruction(Instruction* inst) const { bool modified = false; Instruction* folded_inst(inst); - while (folded_inst->opcode() != SpvOpCopyObject && + while (folded_inst->opcode() != spv::Op::OpCopyObject && FoldInstructionInternal(&*folded_inst)) { modified = true; } |