Fold OpLogicalNot instructions that follow a comparison, if the comparison is only used by that instruction. !(a == b) = (a != b) !(a != b) = (a == b) !(a < b) = (a >= b) !(a >= b) = (a < b) !(a > b) = (a <= b) !(a <= b) = (a > b)
| 3300 | // !(a > b) = (a <= b) |
| 3301 | // !(a <= b) = (a > b) |
| 3302 | FoldingRule FoldLogicalNotComparison() { |
| 3303 | return [](IRContext* context, Instruction* inst, |
| 3304 | const std::vector<const analysis::Constant*>&) { |
| 3305 | assert(inst->opcode() == spv::Op::OpLogicalNot); |
| 3306 | analysis::DefUseManager* def_mgr = context->get_def_use_mgr(); |
| 3307 | Instruction* child = |
| 3308 | context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0)); |
| 3309 | |
| 3310 | if (def_mgr->NumUses(child) > 1) { |
| 3311 | return false; |
| 3312 | } |
| 3313 | |
| 3314 | spv::Op new_opcode = spv::Op::OpNop; |
| 3315 | switch (child->opcode()) { |
| 3316 | // (a == b) <=> (a != b) |
| 3317 | case spv::Op::OpIEqual: |
| 3318 | new_opcode = spv::Op::OpINotEqual; |
| 3319 | break; |
| 3320 | case spv::Op::OpINotEqual: |
| 3321 | new_opcode = spv::Op::OpIEqual; |
| 3322 | break; |
| 3323 | case spv::Op::OpFOrdEqual: |
| 3324 | new_opcode = spv::Op::OpFUnordNotEqual; |
| 3325 | break; |
| 3326 | case spv::Op::OpFOrdNotEqual: |
| 3327 | new_opcode = spv::Op::OpFUnordEqual; |
| 3328 | break; |
| 3329 | case spv::Op::OpFUnordEqual: |
| 3330 | new_opcode = spv::Op::OpFOrdNotEqual; |
| 3331 | break; |
| 3332 | case spv::Op::OpFUnordNotEqual: |
| 3333 | new_opcode = spv::Op::OpFOrdEqual; |
| 3334 | break; |
| 3335 | case spv::Op::OpLogicalEqual: |
| 3336 | new_opcode = spv::Op::OpLogicalNotEqual; |
| 3337 | break; |
| 3338 | case spv::Op::OpLogicalNotEqual: |
| 3339 | new_opcode = spv::Op::OpLogicalEqual; |
| 3340 | break; |
| 3341 | |
| 3342 | // (a > b) <=> (a <= b) |
| 3343 | case spv::Op::OpUGreaterThan: |
| 3344 | new_opcode = spv::Op::OpULessThanEqual; |
| 3345 | break; |
| 3346 | case spv::Op::OpULessThanEqual: |
| 3347 | new_opcode = spv::Op::OpUGreaterThan; |
| 3348 | break; |
| 3349 | case spv::Op::OpSGreaterThan: |
| 3350 | new_opcode = spv::Op::OpSLessThanEqual; |
| 3351 | break; |
| 3352 | case spv::Op::OpSLessThanEqual: |
| 3353 | new_opcode = spv::Op::OpSGreaterThan; |
| 3354 | break; |
| 3355 | case spv::Op::OpFOrdGreaterThan: |
| 3356 | new_opcode = spv::Op::OpFUnordLessThanEqual; |
| 3357 | break; |
| 3358 | case spv::Op::OpFOrdLessThanEqual: |
| 3359 | new_opcode = spv::Op::OpFUnordGreaterThan; |
no test coverage detected