Skip to content

Commit

Permalink
fix(transform): fix some transform bug detected by csmith
Browse files Browse the repository at this point in the history
  • Loading branch information
dtcxzyw committed Jun 17, 2023
1 parent fea60cb commit c6153a8
Show file tree
Hide file tree
Showing 58 changed files with 480 additions and 434 deletions.
5 changes: 5 additions & 0 deletions cmmc/Analysis/AnalysisPass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

#pragma once
#include <any>
#include <cmmc/IR/Function.hpp>
#include <cmmc/IR/Module.hpp>
#include <cmmc/Support/Profiler.hpp>
Expand Down Expand Up @@ -85,6 +86,7 @@ class AnalysisPassManager final {
std::unordered_map<const void*, std::unique_ptr<AnalysisPass<Module>>> mModuleLevelAnalysis;
std::unordered_map<const void*, std::function<std::unique_ptr<AnalysisPass<Function>>()>> mFuncAnalysisBuilder;
std::unordered_map<const void*, std::function<std::unique_ptr<AnalysisPass<Module>>()>> mModuleAnalysisBuilder;
std::unordered_map<const void*, std::any> mPassStorage;

const void* getPassResult(Function& func, const void* id);
const void* getPassResult(const void* id);
Expand Down Expand Up @@ -127,6 +129,9 @@ class AnalysisPassManager final {
void invalidateFunc(Function& func);
void invalidateModule();

std::any& getPassStorage(const void* key) {
return mPassStorage[key];
}
Module& module() const {
return *mModule;
}
Expand Down
6 changes: 4 additions & 2 deletions cmmc/Conversion/LLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,10 @@ class LLVMConversionContext final {
}
case InstructionID::ConditionalBranch: {
const auto branch = inst.as<BranchInst>();
const auto& trueTarget = branch->getTrueTarget();
const auto& falseTarget = branch->getFalseTarget();
const auto trueTarget = branch->getTrueTarget();
const auto falseTarget = branch->getFalseTarget();
if(trueTarget == falseTarget)
return builder.CreateBr(blockMap.lookup(trueTarget));
return builder.CreateCondBr(getOperand(0), blockMap.lookup(trueTarget), blockMap.lookup(falseTarget));
}
case InstructionID::Unreachable:
Expand Down
2 changes: 2 additions & 0 deletions cmmc/ExecutionEngine/LLVMOrcJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ std::variant<int, SimulationFailReason> llvmExecMain(Module& module, const std::
llvmTranslate(module, *llvmMod);

if(llvm::verifyModule(*llvmMod, &llvm::errs())) {
llvmMod->print(llvm::errs(), nullptr);
llvm::errs().flush();
DiagnosticsContext::get().attach<ModuleAttachment>("cmmc IR", &module).reportFatal();
}

Expand Down
2 changes: 2 additions & 0 deletions cmmc/IR/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void Block::dumpLabeled(std::ostream& out, const HighlightSelector& selector) co
if(selector.highlight(this)) {
out << "\033[1;33m";
}
out << " ";
dumpAsTarget(out);
if(selector.highlight(this)) {
out << "\033[0m";
Expand Down Expand Up @@ -157,6 +158,7 @@ void Block::dumpAsTarget(std::ostream& out) const {
Block* Block::clone(std::unordered_map<Value*, Value*>& replace, bool replaceAll) const {
auto block = make<Block>(mFunction);
block->setLabel(getLabel());
block->getTransformMetadata() = mTransformMetadata;

for(auto& inst : mInstructions) {
auto newInst = inst.clone();
Expand Down
8 changes: 8 additions & 0 deletions cmmc/IR/Block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ struct HighlightBlock final : public HighlightSelector {
}
};

struct BlockTransformMetadata final {
uint32_t rotateCount = 0;
};

class Block final {
Function* mFunction;
String mLabel;
uint32_t mBlockIdx;
IntrusiveList<Instruction> mInstructions;
BlockTransformMetadata mTransformMetadata;

public:
explicit Block(Function* function) : mFunction{ function } {}
Expand All @@ -49,6 +54,9 @@ class Block final {
}
void dumpLabeled(std::ostream& out, const HighlightSelector& selector) const;
bool verify(std::ostream& out) const;
BlockTransformMetadata& getTransformMetadata() noexcept {
return mTransformMetadata;
}

[[nodiscard]] Instruction* getTerminator() const noexcept {
return mInstructions.back();
Expand Down
5 changes: 3 additions & 2 deletions cmmc/Transforms/Combine/ArithmeticReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <cmmc/Transforms/Util/PatternMatch.hpp>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <limits>
#include <unordered_map>

Expand Down Expand Up @@ -130,7 +131,7 @@ class ArithmeticReduce final : public TransformPass<Function> {
const auto val = i1 * i2;
const auto width = v1->getType()->as<IntegerType>()->getBitwidth();
const auto min = -(1LL << (width - 1));
const auto max = -(min - 1);
const auto max = -(min + 1);
if(min <= val && val <= max) {
return builder.makeOp<BinaryInst>(InstructionID::SDiv, v1, makeIntLike(val, inst));
}
Expand Down Expand Up @@ -258,7 +259,7 @@ class ArithmeticReduce final : public TransformPass<Function> {
if(c == 1) {
return v1;
}
return builder.getTrue();
return builder.getFalse();
}
if(cmp == CompareOp::NotEqual) {
if(c == 0) {
Expand Down
6 changes: 2 additions & 4 deletions cmmc/Transforms/Combine/ConstantPropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <cmmc/Transforms/Util/BlockUtil.hpp>
#include <cmmc/Transforms/Util/PatternMatch.hpp>
#include <cstdint>
#include <iostream>
#include <unordered_map>

CMMC_NAMESPACE_BEGIN
Expand Down Expand Up @@ -60,7 +61,7 @@ class ConstantPropagation final : public TransformPass<Function> {
}

static bool runOnBlock(IRBuilder& builder, Block& block) {
return reduceBlock(builder, block, [](Instruction* inst) -> Value* {
return reduceBlock(builder, block, [&](Instruction* inst) -> Value* {
intmax_t i1, i2;
uintmax_t u1, u2;
double f1, f2;
Expand All @@ -87,8 +88,6 @@ class ConstantPropagation final : public TransformPass<Function> {

if(inst->isIntegerOp()) {
MatchContext<Value> matchCtx{ inst };
if(not_(int_(i1))(matchCtx))
return makeInt(inst, !i1);
if(neg(int_(i1))(matchCtx))
return makeInt(inst, -i1);
if(add(int_(i1), int_(i2))(matchCtx))
Expand Down Expand Up @@ -223,7 +222,6 @@ class ConstantPropagation final : public TransformPass<Function> {
return inst->getOperand(1);
}
}

return nullptr;
});
}
Expand Down
9 changes: 9 additions & 0 deletions cmmc/Transforms/ControlFlow/ShortCircuitCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ class ShortCircuitCombine final : public TransformPass<Function> {
case InstructionID::Store:
[[fallthrough]];
case InstructionID::Call:
[[fallthrough]];
// It is not safe to speculate division, since SIGFPE may be raised.
case InstructionID::SDiv:
[[fallthrough]];
case InstructionID::UDiv:
[[fallthrough]];
case InstructionID::SRem:
[[fallthrough]];
case InstructionID::URem:
return false;
case InstructionID::Load: {
const auto addr = inst.getOperand(0);
Expand Down
11 changes: 11 additions & 0 deletions cmmc/Transforms/Loop/LoopRotate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
limitations under the License.
*/

#include "cmmc/Analysis/AnalysisPass.hpp"
#include <algorithm>
#include <cmmc/Analysis/CFGAnalysis.hpp>
#include <cmmc/Analysis/DominateAnalysis.hpp>
#include <cmmc/IR/Block.hpp>
Expand All @@ -20,6 +22,7 @@
#include <cmmc/IR/Instruction.hpp>
#include <cmmc/Transforms/TransformPass.hpp>
#include <cmmc/Transforms/Util/BlockUtil.hpp>
#include <cstdint>
#include <iterator>
#include <unordered_map>
#include <unordered_set>
Expand Down Expand Up @@ -47,6 +50,8 @@ struct SimpleLoopInfo final {
Block* latch;
};

constexpr uint32_t maxRotateCount = 8;

class LoopRotate final : public TransformPass<Function> {
static std::vector<SimpleLoopInfo> detectLoops(Function& func, AnalysisPassManager& analysis) {
std::vector<SimpleLoopInfo> ret;
Expand Down Expand Up @@ -92,6 +97,12 @@ class LoopRotate final : public TransformPass<Function> {
// TODO: create new block for phi nodes
if(cfg.predecessors(exiting).size() != 1)
continue;
auto& rotateCount = loop.latch->getTransformMetadata().rotateCount;
if(rotateCount < maxRotateCount) {
++rotateCount;
rotateCount = std::max(loop.header->getTransformMetadata().rotateCount, rotateCount);
} else
continue;

// duplicate instructions
std::unordered_map<Value*, PhiInst*> replace;
Expand Down
2 changes: 1 addition & 1 deletion cmmc/Transforms/Merge/CSE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class SimpleCSE final : public TransformPass<Function> {
if(unique)
phiList.push_back(lhs);
} else {
if(!isMovableExpr(inst))
if(!isMovableExpr(inst, false))
continue;

if(auto [iter, res] = lut.insert(&inst); !res) {
Expand Down
4 changes: 2 additions & 2 deletions cmmc/Transforms/Merge/GVN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class GVN final : public TransformPass<Function> {
const auto root = value;
if(root->isInstruction()) {
const auto inst = root->as<Instruction>();
if(isMovableExpr(*inst))
if(isMovableExpr(*inst, false))
return getInstNumber(inst);
}

Expand All @@ -133,7 +133,7 @@ class GVN final : public TransformPass<Function> {

for(auto block : dom.blocks()) {
for(auto& inst : block->instructions()) {
if(!isMovableExpr(inst))
if(!isMovableExpr(inst, false))
continue;

const auto id = getInstNumber(&inst);
Expand Down
2 changes: 1 addition & 1 deletion cmmc/Transforms/Misc/BlockReorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ class BlockReorder final : public TransformPass<Function> {
if(inst.getInstID() == InstructionID::Phi || inst.getInstID() == InstructionID::Alloc || inst.isTerminator())
continue;
const uint32_t idx = count++;
if(!isMovableExpr(inst)) {
if(!isMovableExpr(inst, false)) {
if(lastInstWithSideEffects) {
addEdge(idx, lastInstWithSideEffects);
}
Expand Down
2 changes: 1 addition & 1 deletion cmmc/Transforms/Misc/CodeMove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CodeMove final : public TransformPass<Function> {
std::unordered_set<Value*> moveOutSet;

for(auto& inst : block->instructions()) {
if(!isMovableExpr(inst))
if(!isMovableExpr(inst, true))
continue;

// don't touch not natively supported instructions as GVN does
Expand Down
2 changes: 1 addition & 1 deletion cmmc/Transforms/Misc/CodeSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class CodeSink final : public TransformPass<Function> {
for(auto iter = instructions.begin(); iter != instructions.end();) {
auto next = std::next(iter);
auto& inst = *iter;
if(isMovableExpr(inst)) {
if(isMovableExpr(inst, false)) {
if(moveToTrueTarget) {
if(tryMove(&inst, trueTarget)) {
modified = true;
Expand Down
5 changes: 4 additions & 1 deletion cmmc/Transforms/Misc/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,11 @@ class SROA final : public TransformPass<Function> {
Value* sub = nullptr;
if(int_(idxInt)(MatchContext<Value>{ idx })) {
sub = map[static_cast<size_t>(idxInt)];
} else {
} else if(idx->is<ConstantOffset>()) {
sub = map[idx->as<ConstantOffset>()->index()];
} else {
// [1 * type]
sub = map[0];
}
operands.erase(std::next(operands.begin()));
operands.pop_back();
Expand Down
5 changes: 4 additions & 1 deletion cmmc/Transforms/TransformPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ static void cleanupUnusedInsts(Module& module) {
template <typename Scope>
std::optional<size_t> PassManager<Scope>::run(Scope& item, AnalysisPassManager& analysis, size_t lastStop) const {
auto dumpItem = [&] {
if(runCount < skipCount.get())
return;
if constexpr(std::is_same_v<Function, Scope>)
item.dump(std::cerr, Noop{});
else
Expand Down Expand Up @@ -295,7 +297,8 @@ class FunctionPassWrapper final : public TransformPass<Module> {
if(mPass->run(*func, analysis)) {
if(debugTransform.get()) {
std::cerr << "\tmodified" << std::endl;
func->dump(std::cerr, Noop{});
if(runCount >= skipCount.get())
func->dump(std::cerr, Noop{});
}
analysis.invalidateFunc(*func);
modified = true;
Expand Down
19 changes: 17 additions & 2 deletions cmmc/Transforms/Util/BlockUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ bool reduceBlock(IRBuilder& builder, Block& block, const BlockReducer& reducer)
// block.dump(std::cerr, HighlightInst{ &inst });
builder.setInsertPoint(&block, iter);
if(auto value = reducer(&inst)) {
/*
inst.dumpInst(std::cerr);
std::cerr << " => ";
value->dumpAsOperand(std::cerr);
std::cerr << '\n';
*/
modified |= inst.replaceWith(value);
}
}
Expand Down Expand Up @@ -101,7 +107,7 @@ Block* createIndirectBlock(const Module& module, Function& func, Block* sourceBl
terminator->getTrueTarget() = block;
if(terminator->getFalseTarget() == targetBlock)
terminator->getFalseTarget() = block;

block->getTransformMetadata() = sourceBlock->getTransformMetadata();
retargetBlock(targetBlock, sourceBlock, block);
return block;
}
Expand Down Expand Up @@ -129,7 +135,7 @@ bool isNoSideEffectExpr(const Instruction& inst) {

return true;
}
bool isMovableExpr(const Instruction& inst) {
bool isMovableExpr(const Instruction& inst, bool relaxedCtx) {
if(!isNoSideEffectExpr(inst))
return false;
switch(inst.getInstID()) {
Expand All @@ -139,6 +145,15 @@ bool isMovableExpr(const Instruction& inst) {
[[fallthrough]];
case InstructionID::Load:
return false;
// It is not safe to speculate division, since SIGFPE may be raised.
case InstructionID::SDiv:
[[fallthrough]];
case InstructionID::UDiv:
[[fallthrough]];
case InstructionID::SRem:
[[fallthrough]];
case InstructionID::URem:
return !relaxedCtx;
default:
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion cmmc/Transforms/Util/BlockUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ bool applyReplace(Instruction* inst, const ReplaceMap& replace);
bool replaceOperands(const std::vector<Instruction*>& insts, const ReplaceMap& replace);
Block* createIndirectBlock(const Module& module, Function& func, Block* sourceBlock, Block* targetBlock);
bool isNoSideEffectExpr(const Instruction& inst);
bool isMovableExpr(const Instruction& inst);
bool isMovableExpr(const Instruction& inst, bool relaxedCtx);
bool hasCall(Block& block);
void resetTarget(BranchInst* branch, Block* oldTarget, Block* newTarget);
void retargetBlock(Block* target, Block* oldSource, Block* newSource);
Expand Down
Loading

0 comments on commit c6153a8

Please sign in to comment.