[Please keep pkg-clamav-devel@lists.alioth.debian.org in CC.]

Hi,

I nearly finished adapting clamav to LLVM 3.6, just one problem remains:
The Sparse Conditional Constant Propagation optimization doesn't work anymore.

I have created a small example program demonstrating the problem (attached).

It works fine with LLVM 3.5:
$ make
$ ./test
LLVM module:
---------
; ModuleID = 'test'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define i32 @test() {
EntryBlock:
  ret i32 1
}
---------
verifying...
starting test() with JIT...
Result: 1

But it fails with LLVM 3.6:
$ make LLVM=3.6
$ ./test
Pass 'Sparse Conditional Constant Propagation' is not initialized.
Verify if there is a pass dependency cycle.
Required Passes:
Segmentation fault (core dumped)

It's a rather strange error message, because there can't be a dependency cycle, if there are no required passes.

The reason for the behavior change is that in LLVM 3.6 the JIT compiler got removed so that the MCJIT one is now used by default.
Using the MCJIT compiler in LLVM 3.5 also shows the problem:

$ make MCJIT=1
$ ./test
Pass 'Sparse Conditional Constant Propagation' is not initialized.
Verify if there is a pass dependency cycle.
Required Passes:
Segmentation fault (core dumped)

Disabling the SCCP pass avoids this segfault, but then the optimizations are missing (obviously):
$ make SCCP=0 LLVM=3.6
$ ./test
LLVM module:
---------
; ModuleID = 'test'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define i32 @test() {
EntryBlock:
  %cond = icmp sle i32 1, 2
  br i1 %cond, label %return, label %test

return: ; preds = %test, %EntryBlock
  ret i32 1

test: ; preds = %EntryBlock, %test
  %arg = add i32 1, 2
  %cond2 = icmp sle i32 1, %arg
  br i1 %cond2, label %return, label %test
}
---------
verifying...
starting test() with JIT...
Result: 1


Thus I'm wondering if there is a way to make the SCCP pass work with MCJIT or is this a bug in LLVM?

Best regards,
Andreas
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#if LLVM_VERSION < 36
#include "llvm/ExecutionEngine/JIT.h"
#endif
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/Scalar.h"

using namespace llvm;

int main(int argc, char **argv) {
  InitializeNativeTarget();
  InitializeNativeTargetAsmPrinter();
  InitializeNativeTargetAsmParser();

  LLVMContext Context;
  Module *M = new Module("test", Context);

  // create Function
  Function *F = cast<Function>(M->getOrInsertFunction("test",
                                                      Type::getInt32Ty(Context),
                                                      (Type *)0));

  // Add a basic block to the function.
  BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", F);
  // Create an exit block.
  BasicBlock *RetBB = BasicBlock::Create(Context, "return", F);
  // Create the test block.
  BasicBlock *TestBB = BasicBlock::Create(Context, "test", F);

  // Get pointers to the constants.
  Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1);
  Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2);

  // Create: if (1 < 2) then goto return else goto test
  Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, One, Two, "cond");
  BranchInst::Create(RetBB, TestBB, CondInst, BB);

  // Create: if (1 < 3) then goto return else goto test
  // This codepath can never be reached.
  Value *Add = BinaryOperator::CreateAdd(One, Two, "arg", TestBB);
  Value *CondInst2 = new ICmpInst(*TestBB, ICmpInst::ICMP_SLE, One, Add, "cond2");
  BranchInst::Create(RetBB, TestBB, CondInst2, TestBB);

  // Create: ret int 1
  ReturnInst::Create(Context, One, RetBB);

  // create JIT
  std::string errStr;
#if LLVM_VERSION < 36
  EngineBuilder builder(M);
#if USE_MCJIT
  builder.setUseMCJIT(true);
#endif
#else
  EngineBuilder builder(std::move(std::unique_ptr<Module>(M)));
#endif

  builder.setErrorStr(&errStr);
  builder.setEngineKind(EngineKind::JIT);

  ExecutionEngine *EE = builder.create();

  if (!EE) {
    errs() << "Failed to construct ExecutionEngine: " << errStr << "\n";
    return 1;
  }

  PassManager PM;
#if USE_SCCP
  PM.add(createSCCPPass());
#endif
  PM.add(createCFGSimplificationPass());
  PM.run(*M);

  EE->finalizeObject();

  errs() << "LLVM module:\n---------\n" << *M << "---------\n";
  errs() << "verifying... \n";
  if (verifyModule(*M, &errs())) {
    errs() << argv[0] << "Error constructing function!\n";
    return 1;
  }

  errs() << "starting test() with JIT...\n";
  std::vector<GenericValue> Args(0);
  GenericValue GV = EE->runFunction(F, Args);

  outs() << "Result: " << GV.IntVal << "\n";

  return 0;
}
LLVM  := 3.5
MCJIT := 0
SCCP  := 1

LLVM_VERSION=$(shell echo $(LLVM) | sed 's/\.//')

CXXFLAGS := -Wall -g -std=c++11 -I/usr/include/llvm-$(LLVM)/ 
-I/usr/include/llvm-c-$(LLVM) -DLLVM_VERSION=$(LLVM_VERSION) 
-DUSE_MCJIT=$(MCJIT) -DUSE_SCCP=$(SCCP) -DNDEBUG
LDLIBS := -lLLVM-$(LLVM) -lstdc++ $(LDLIBS)
LDFLAGS := -L/usr/lib/llvm-$(LLVM)/lib

EXAMPLES=test

OBJS=$(addsuffix .o,$(EXAMPLES))

.phony: all clean

all: $(OBJS) $(EXAMPLES)

clean:
        $(RM) $(EXAMPLES) $(OBJS)
_______________________________________________
Pkg-clamav-devel mailing list
Pkg-clamav-devel@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-clamav-devel

Reply via email to