Fold OpSelect instructions which have constant booleans as their result. x ? true : false = x x ? false : true = !x
| 3064 | // x ? true : false = x |
| 3065 | // x ? false : true = !x |
| 3066 | FoldingRule FoldConstantBooleanSelect() { |
| 3067 | return [](IRContext* context, Instruction* inst, |
| 3068 | const std::vector<const analysis::Constant*>& constants) { |
| 3069 | assert(inst->opcode() == spv::Op::OpSelect); |
| 3070 | assert(inst->NumInOperands() == 3); |
| 3071 | assert(constants.size() == 3); |
| 3072 | |
| 3073 | if (!constants[1] || !constants[2]) { |
| 3074 | return false; |
| 3075 | } |
| 3076 | |
| 3077 | analysis::DefUseManager* def_mgr = context->get_def_use_mgr(); |
| 3078 | if (inst->type_id() != |
| 3079 | def_mgr->GetDef(inst->GetSingleWordInOperand(0))->type_id()) { |
| 3080 | return false; |
| 3081 | } |
| 3082 | |
| 3083 | std::optional<bool> uniform_true = GetBoolConstantKind(constants[1]); |
| 3084 | std::optional<bool> uniform_false = GetBoolConstantKind(constants[2]); |
| 3085 | |
| 3086 | if (!uniform_true || !uniform_false) { |
| 3087 | return false; |
| 3088 | } |
| 3089 | |
| 3090 | if (uniform_true.value() && !uniform_false.value()) { |
| 3091 | inst->SetOpcode(spv::Op::OpCopyObject); |
| 3092 | inst->SetInOperands( |
| 3093 | {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}}); |
| 3094 | return true; |
| 3095 | } else if (!uniform_true.value() && uniform_false.value()) { |
| 3096 | inst->SetOpcode(spv::Op::OpLogicalNot); |
| 3097 | inst->SetInOperands( |
| 3098 | {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}}); |
| 3099 | return true; |
| 3100 | } |
| 3101 | return false; |
| 3102 | }; |
| 3103 | } |
| 3104 | |
| 3105 | // Fold OpLogicalAnd instructions which have a constant true on one side. |
| 3106 | // x && true = x |
no test coverage detected