diff --git a/lib/Infer/AbstractInterpreter.cpp b/lib/Infer/AbstractInterpreter.cpp index 006a24578..be15cca24 100644 --- a/lib/Infer/AbstractInterpreter.cpp +++ b/lib/Infer/AbstractInterpreter.cpp @@ -686,30 +686,34 @@ namespace souper { } break; } -// case ExtractValue: -// return "extractvalue"; -// case SAddWithOverflow: -// return "sadd.with.overflow"; -// case UAddWithOverflow: -// return "uadd.with.overflow"; -// case SSubWithOverflow: -// return "ssub.with.overflow"; -// case USubWithOverflow: -// return "usub.with.overflow"; -// case SMulWithOverflow: -// return "smul.with.overflow"; -// case UMulWithOverflow: -// return "umul.with.overflow"; + case souper::Inst::ExtractValue: { + if (I->Ops[1]->Val == 0) { + auto IOld = I; + I = I->Ops[0]->Ops[0]; + switch (IOld->Ops[0]->K) { + case souper::Inst::SAddWithOverflow: + case souper::Inst::UAddWithOverflow: + return BinaryTransferFunctionsKB::add(KB0, KB1); + + case souper::Inst::SSubWithOverflow: + case souper::Inst::USubWithOverflow: + return BinaryTransferFunctionsKB::sub(KB0, KB1); + + case souper::Inst::SMulWithOverflow: + case souper::Inst::UMulWithOverflow: + return BinaryTransferFunctionsKB::mul(KB0, KB1); + default: + llvm::report_fatal_error("Wrong operand in ExtractValue."); + } + I = IOld; // needed for caching + } + // returns TOP for the carry bit + } + // case ReservedConst: // return "reservedconst"; // case ReservedInst: // return "reservedinst"; -// case SAddO: -// case UAddO: -// case SSubO: -// case USubO: -// case SMulO: -// case UMulO: default : break; } @@ -858,6 +862,30 @@ namespace souper { // return R0.sdiv(R1); // unimplemented // } // TODO: Xor pattern for not, truncs and extends, etc + case souper::Inst::ExtractValue: { + if (I->Ops[1]->Val == 0) { + auto IOld = I; + I = I->Ops[0]->Ops[0]; + switch (IOld->Ops[0]->K) { + case souper::Inst::SAddWithOverflow: + case souper::Inst::UAddWithOverflow: + return CR0.add(CR1); + + case souper::Inst::SSubWithOverflow: + case souper::Inst::USubWithOverflow: + return CR0.sub(CR1); + + case souper::Inst::SMulWithOverflow: + case souper::Inst::UMulWithOverflow: + return CR0.multiply(CR1); + default: + llvm::errs() << Inst::getKindName(I->Ops[0]->K) << "\n"; + llvm::report_fatal_error("Wrong operand in ExtractValue."); + } + I = IOld; // needed for caching + } + // returns TOP for the carry bit + } default: break; }