diff --git a/hpvm/projects/hetero-c++/include/DFGUtils.h b/hpvm/projects/hetero-c++/include/DFGUtils.h index 99543610a1f44e8812dd4c6b5f7a484a74f96043..c2f90c39d123b1fb458b76c870d7024a999e5d51 100644 --- a/hpvm/projects/hetero-c++/include/DFGUtils.h +++ b/hpvm/projects/hetero-c++/include/DFGUtils.h @@ -133,3 +133,4 @@ bool isPrivCall(CallInst* CI); bool isNonZeroCall(CallInst* CI); +Value* castIntegerToBitwidth(Value* V, Instruction* InsertBefore, int BV); diff --git a/hpvm/projects/hetero-c++/lib/DFGUtils.cpp b/hpvm/projects/hetero-c++/lib/DFGUtils.cpp index fcb92815c7e2ec60d817e9b541ef321af5f247f6..63be8a449cf49fc92da330053421be257127d556 100644 --- a/hpvm/projects/hetero-c++/lib/DFGUtils.cpp +++ b/hpvm/projects/hetero-c++/lib/DFGUtils.cpp @@ -489,6 +489,7 @@ Function* CreateClone(Function* Orig, std::set<Argument*> Exclude, ValueToValueM if(MappedInst){ LLVM_DEBUG(dbgs()<<"Removing :"<<*MappedInst<<"\n"); + MappedInst->replaceAllUsesWith(UndefValue::get(MappedInst->getType())); MappedInst->eraseFromParent(); } @@ -1264,7 +1265,6 @@ bool isPrivCall(CallInst* CI){ return (CF->getName() == "__hpvm_priv") ||(CF->getName() == "__hetero_priv") ; - } @@ -1280,4 +1280,26 @@ bool isNonZeroCall(CallInst* CI){ } +Value* castIntegerToBitwidth(Value* V, Instruction* InsertBefore, int BV){ + LLVMContext& LC = V->getContext(); + + + IntegerType* IType = IntegerType::get(LC, BV); + + if(V->getType()->isIntegerTy(BV)){ + return V; + } else { + IntegerType* SizeTy = dyn_cast<IntegerType>(V->getType()); + assert(SizeTy && "Dimension size must be an integer type"); + Value* CastToI = nullptr; + + if(SizeTy->getBitWidth() > BV){ + return new TruncInst(V, IType, "trunc_", InsertBefore); + } else { + return new SExtInst(V, IType, "sext_", InsertBefore); + } + } +} + + diff --git a/hpvm/projects/hetero-c++/lib/HCCVerifier.cpp b/hpvm/projects/hetero-c++/lib/HCCVerifier.cpp index c6a34f2025fbbfc0f134ad18b2cfcfc696f19ec0..b2acc2caa86069ad5282ace5bbe5b6a8d5f2cd4d 100644 --- a/hpvm/projects/hetero-c++/lib/HCCVerifier.cpp +++ b/hpvm/projects/hetero-c++/lib/HCCVerifier.cpp @@ -526,7 +526,9 @@ bool HCCVerifier::verifyUses(RegionTree& region, std::set<Value*> inputs, && "verifyUses() requires outerInputs for loops"); if (region.contains.empty()) { // A region with code in it, so actually check the operands used - std::set<Instruction*> outsideValues; + // Track the values from outside the region used in it (and track in the + // bool whether the value is used by the loop condition for parallel loops) + std::set<std::pair<Instruction*, bool>> outsideValues; Instruction* start = region.start->getNextNonDebugInstruction(); Instruction* end = region.end; @@ -576,7 +578,7 @@ bool HCCVerifier::verifyUses(RegionTree& region, std::set<Value*> inputs, // side-effect free and don't touch memory, because these are the // only ones that are safe to then rematerialize in the task // (possibly in multiple tasks or multiple iterations) - outsideValues.insert(inst); + outsideValues.insert(std::make_pair(inst, isLoopCond)); } else { errors = true; reportErrorOnInst("Cannot use value defined outside of this " @@ -602,14 +604,17 @@ bool HCCVerifier::verifyUses(RegionTree& region, std::set<Value*> inputs, } // Convert to a vector so we can add elements to it as we traverse - std::vector<Instruction*> values(outsideValues.begin(), outsideValues.end()); + std::vector<std::pair<Instruction*, bool>> + values(outsideValues.begin(), outsideValues.end()); // We now process all of the operands that are values from instructions // outside of the region or that otherwise come from outside of the region. for (unsigned int i = 0; i < values.size(); i++) { - Instruction* inst = values[i]; + Instruction* inst = values[i].first; + bool isLoopCond = values[i].second; for (Value* op : inst->operands()) { - if (inputs.find(op) == inputs.end()) { + if (inputs.find(op) == inputs.end() + && (!isLoopCond || outerInputs->find(op) == outerInputs->end())) { Instruction* ins = dyn_cast<Instruction>(op); Constant* const_ = dyn_cast<Constant>(op); BasicBlock* block = dyn_cast<BasicBlock>(op); @@ -620,10 +625,11 @@ bool HCCVerifier::verifyUses(RegionTree& region, std::set<Value*> inputs, && !ins->mayReadOrWriteMemory()) { // Add to the list to verify, to make sure that all operands these // instructions depend on satisfy these properties - auto f = outsideValues.find(ins); + std::pair<Instruction*, bool> pair = std::make_pair(ins, isLoopCond); + auto f = outsideValues.find(pair); if (f == outsideValues.end()) { - outsideValues.insert(ins); - values.push_back(ins); + outsideValues.insert(pair); + values.push_back(pair); } } else { errors = true; diff --git a/hpvm/projects/hetero-c++/lib/HPVMCGen.cpp b/hpvm/projects/hetero-c++/lib/HPVMCGen.cpp index 00dccd715c548f83e70acdc7bf9976574b670840..863d0561654e6f072deeb5b4062d3668bf5e7b6e 100644 --- a/hpvm/projects/hetero-c++/lib/HPVMCGen.cpp +++ b/hpvm/projects/hetero-c++/lib/HPVMCGen.cpp @@ -231,8 +231,28 @@ CallInst* HPVMCGenCreateNodeND::insertCallND(Instruction* insertBefore, ConstantInt* dimSizeConst = ConstantInt::get(dimSizeType, dimSizeVec.size()); argsVec.push_back(dimSizeConst); argsVec.push_back(nodeFunc); - for (auto d: dimSizeVec) - argsVec.push_back(d); + + IntegerType* I64Type = IntegerType::get(theContext.getLLVMContext(), 64); + for (auto d: dimSizeVec){ + if(!d->getType()->isIntegerTy(64)){ + + IntegerType* SizeTy = dyn_cast<IntegerType>(d->getType()); + assert(SizeTy && "Dimension size must be an integer type"); + Value* CastToI64 = nullptr; + + if(SizeTy->getBitWidth() > 64){ + // trunc + CastToI64 = new TruncInst(d, I64Type, "trunc_", insertBefore); + } else { + + CastToI64 = new SExtInst(d, I64Type, "sext_", insertBefore); + } + argsVec.push_back(CastToI64); + + } else { + argsVec.push_back(d); + } + } ArrayRef<Value *> argsList(argsVec); // safe: argsList not needed after return CallInst* newCall = this->insertCall(insertBefore, funcName, argsList); if (! newCall) HPVMWarnError("CreateNodeND function not VarArgs?"); diff --git a/hpvm/projects/hetero-c++/lib/HPVMExtractTask.cpp b/hpvm/projects/hetero-c++/lib/HPVMExtractTask.cpp index 5142f228e20eda138722c06c30c5b7cc2db57919..9d18030ef083f66450d9df8b95377d648aa65ce6 100644 --- a/hpvm/projects/hetero-c++/lib/HPVMExtractTask.cpp +++ b/hpvm/projects/hetero-c++/lib/HPVMExtractTask.cpp @@ -2946,7 +2946,11 @@ CallInst* HPVMProgram::parallelizeLoop(/*Loop* ExtractedLoop, Loop* InnerLoop*/ } - InductionVar->replaceAllUsesWith(getIDCall); + IntegerType* IVTy = dyn_cast<IntegerType>(InductionVar->getType()); + assert(IVTy && "Induction Variable must be of integer type"); + + Value* MatchedType = castIntegerToBitwidth(getIDCall, getIDCall->getNextNode(), IVTy->getBitWidth()); + InductionVar->replaceAllUsesWith(MatchedType); cast<Instruction>(InductionVar)->eraseFromParent(); diff --git a/hpvm/projects/hetero-c++/test/integration/src/loopbound_calc.cc b/hpvm/projects/hetero-c++/test/integration/src/loopbound_calc.cc new file mode 100644 index 0000000000000000000000000000000000000000..b59a5e8fe087a8f0ec7adce7489e23bf90828c18 --- /dev/null +++ b/hpvm/projects/hetero-c++/test/integration/src/loopbound_calc.cc @@ -0,0 +1,28 @@ +#include <stdlib.h> +#include <stdio.h> +#include "heterocc.h" + +void dummy(size_t bytes_prod, size_t matrix_dim) { + void* Section = __hetero_section_begin(); + + int loop_size = matrix_dim / sizeof(int); + + for(int i = 0; i < loop_size; ++i){ + __hetero_parallel_loop( + /* Number of parallel enclosing loops */ 1, + /* Number of Input Buffer Pairs */ 1, bytes_prod, + /* Number of Output Buffer Pairs */ 1, bytes_prod); + printf("success"); + + } + + __hetero_section_end(Section); +} + +int main() { + size_t x = 3, y = 7; + auto l = __hetero_launch((void*)dummy, 2, x, y, 0); + __hetero_wait(l); + + return 0; +}