<commit_before>#ifndef _LLVM_DG_SLICER_H_
#define _LLVM_DG_SLICER_H_

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/CFG.h>
#include <llvm/Support/raw_ostream.h>

#include "analysis/Slicing.h"
#include "LLVMDependenceGraph.h"
#include "LLVMNode.h"

namespace dg {

class LLVMNode;

class LLVMSlicer : public analysis::Slicer<LLVMNode>
{
public:
    LLVMSlicer(){}

    void keepFunctionUntouched(const char *n)
    {
        dont_touch.insert(n);
    }

    /* virtual */
    bool removeNode(LLVMNode *node)
    {
        using namespace llvm;

        Value *val = const_cast<Value *>(node->getKey());
        // if there are any other uses of this value,
        // just replace them with undef
        val->replaceAllUsesWith(UndefValue::get(val->getType()));

        Instruction *Inst = dyn_cast<Instruction>(val);
        if (Inst) {
            Inst->eraseFromParent();
        } else {
            GlobalVariable *GV = dyn_cast<GlobalVariable>(val);
            if (GV)
                GV->eraseFromParent();
        }

        return true;
    }

    /* virtual */
    void removeBlock(LLVMBBlock *block)
    {
        assert(block);

        const llvm::Value *val = block->getKey();
        if (val == nullptr)
            return;

        llvm::Value *llvmval = const_cast<llvm::Value *>(val);
        llvm::BasicBlock *blk = llvm::cast<llvm::BasicBlock>(llvmval);

        //llvm::errs() << "Deleting: " << *blk << "\n===\n";

        LLVMDependenceGraph *dg = block->getDG();
        dg->getBlocks().erase(blk);

        for (auto succ : block->successors()) {
            if (succ.label == 255)
                continue;

            llvm::Value *sval = const_cast<llvm::Value *>(succ.target->getKey());
            if (sval) {
                llvm::cast<llvm::BasicBlock>(sval)->removePredecessor(blk);
            }
        }

        blk->eraseFromParent();
    }

    // override slice method
    uint32_t slice(LLVMNode *start, uint32_t sl_id = 0)
    {
        (void) sl_id;
        (void) start;

        assert(0 && "Do not use this method with LLVM dg");
        return 0;
    }

    uint32_t slice(LLVMDependenceGraph *maindg,
                   LLVMNode *start, uint32_t sl_id = 0)
    {
        // mark nodes for slicing
        assert(start || sl_id != 0);
        if (start)
            sl_id = mark(start, sl_id);

        // take every subgraph and slice it intraprocedurally
        // this includes the main graph
        extern std::map<const llvm::Value *,
                        LLVMDependenceGraph *> constructedFunctions;
        for (auto it : constructedFunctions) {<commit_msg>llvm-dg: fix slicing away PHI nodes<commit_after>#ifndef _LLVM_DG_SLICER_H_
#define _LLVM_DG_SLICER_H_

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/CFG.h>
#include <llvm/Support/raw_ostream.h>

#include "analysis/Slicing.h"
#include "LLVMDependenceGraph.h"
#include "LLVMNode.h"

namespace dg {

class LLVMNode;

class LLVMSlicer : public analysis::Slicer<LLVMNode>
{
public:
    LLVMSlicer(){}

    void keepFunctionUntouched(const char *n)
    {
        dont_touch.insert(n);
    }

    /* virtual */
    bool removeNode(LLVMNode *node)
    {
        using namespace llvm;

        Value *val = const_cast<Value *>(node->getKey());
        // if there are any other uses of this value,
        // just replace them with undef
        val->replaceAllUsesWith(UndefValue::get(val->getType()));

        Instruction *Inst = dyn_cast<Instruction>(val);
        if (Inst) {
            Inst->eraseFromParent();
        } else {
            GlobalVariable *GV = dyn_cast<GlobalVariable>(val);
            if (GV)
                GV->eraseFromParent();
        }

        return true;
    }

    static void
    adjustPhiNodes(llvm::BasicBlock *pred, llvm::BasicBlock *blk)
    {
        using namespace llvm;

        for(Instruction& I : *pred) {
            PHINode *phi = dyn_cast<PHINode>(&I);
            if (phi) {
                // the second argument is DeletePHIIFEmpty.
                // We don't want that, since that would make
                // dependence graph inconsistent. We'll
                // slice it away later, if it's empty
                phi->removeIncomingValue(blk, false);
            } else {
                // phi nodes are always at the beginning of the block
                // so if this is the first value that is not PHI,
                // there won't be any other and we can bail out
                break;
            }
        }
    }

    /* virtual */
    void removeBlock(LLVMBBlock *block)
    {
        assert(block);

        const llvm::Value *val = block->getKey();
        if (val == nullptr)
            return;

        llvm::Value *llvmval = const_cast<llvm::Value *>(val);
        llvm::BasicBlock *blk = llvm::cast<llvm::BasicBlock>(llvmval);

        //llvm::errs() << "Deleting: " << *blk << "\n===\n";

        LLVMDependenceGraph *dg = block->getDG();
        dg->getBlocks().erase(blk);

        for (auto succ : block->successors()) {
            if (succ.label == 255)
                continue;

            llvm::Value *sval = const_cast<llvm::Value *>(succ.target->getKey());
            if (sval)
                adjustPhiNodes(llvm::cast<llvm::BasicBlock>(sval), blk);
        }

        blk->eraseFromParent();
    }

    // override slice method
    uint32_t slice(LLVMNode *start, uint32_t sl_id = 0)
    {
        (void) sl_id;
        (void) start;

        assert(0 && "Do not use this method with LLVM dg");
        return 0;
    }

    uint32_t slice(LLVMDependenceGraph *maindg,
                   LLVMNode *start, uint32_t sl_id = 0)
    {
        // mark nodes for slicing
        assert(start || sl_id != 0);
        if (start)
            sl_id = mark(start, sl_id);

        // take every subgraph and slice it intraprocedurally
        // this includes the main graph
        extern std::map<const llvm::Value *,
                        LLVMDependenceGraph *> constructedFunctions;
        for (auto it : constructedFunctions) {
{'fraction_non_alphanumeric': 0.12461957392279353, 'fraction_numerical': 0.005125740829729297, 'mean_word_length': 2.047340165934602, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '303974', 'n_tokens_mistral': 2006, 'n_tokens_neox': 1906, 'n_words': 456}