From 9f064354cef7a35cb438e415c47225399d99922f Mon Sep 17 00:00:00 2001 From: Prakalp Srivastava <psrivas2@illinois.edu> Date: Sun, 20 Mar 2016 14:32:20 -0500 Subject: [PATCH] Added support for umin and umax visc intrinsics --- llvm/include/llvm/IR/IntrinsicsVISC.td | 8 ++++ .../DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp | 39 +++++++++++++++---- llvm/lib/Transforms/GenVISC/GenVISC.cpp | 8 ++++ llvm/test/VISC/parboil/common/include/visc.h | 2 + .../datasets/histo/large/input/DESCRIPTION | 2 +- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/IR/IntrinsicsVISC.td b/llvm/include/llvm/IR/IntrinsicsVISC.td index cb30dffe52..218f34d7da 100644 --- a/llvm/include/llvm/IR/IntrinsicsVISC.td +++ b/llvm/include/llvm/IR/IntrinsicsVISC.td @@ -205,10 +205,18 @@ let TargetPrefix = "visc" in { def int_visc_atomic_min: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], []>; + /* i32 llvm.visc.atomic.umin(i32*, i32)*/ + def int_visc_atomic_umin: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + []>; + /* i32 llvm.visc.atomic.maxi32*, i32)*/ def int_visc_atomic_max: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], []>; + /* i32 llvm.visc.atomic.umaxi32*, i32)*/ + def int_visc_atomic_umax: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + []>; + // Atomic bitwise operations /* i32 llvm.visc.atomic.and(i32*, i32)*/ diff --git a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp index 1660493aa0..dac22fe3d8 100644 --- a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp +++ b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp @@ -1314,7 +1314,9 @@ void CGT_NVPTX::codeGen(DFLeafNode* N) { case Intrinsic::visc_atomic_sub: case Intrinsic::visc_atomic_xchg: case Intrinsic::visc_atomic_min: + case Intrinsic::visc_atomic_umin: case Intrinsic::visc_atomic_max: + case Intrinsic::visc_atomic_umax: case Intrinsic::visc_atomic_and: case Intrinsic::visc_atomic_or: case Intrinsic::visc_atomic_xor: @@ -1694,24 +1696,40 @@ void CGT_NVPTX::transformFunctionToVoid(Function* F) { // 1. No stores // 2. Loads not dependent on getNodeInstanceID itrinsic -static bool findLoadStoreUses(Value* V, std::vector<Value*>*UseList) { - for(Value::use_iterator ui = V->use_begin(), ue = V->use_end(); +static bool findLoadStoreUses(Value* V, std::vector<Value*>*UseList, std::vector<Value*>*VisitedList) { + if(std::find(VisitedList->begin(), VisitedList->end(), V) != VisitedList->end()) { + DEBUG(errs() << "\tAlready visited value: " << *V << "\n"); + return false; + } + VisitedList->push_back(V); + for(Value::use_iterator ui = V->use_begin(), ue = V->use_end(); ui != ue; ++ui) { - Value* I = *ui; + Instruction* I = dyn_cast<Instruction>(*ui); + if(!I) { + // if use is not an instruction, then skip it + continue; + } DEBUG(errs() << "\t" << *I << "\n"); if(isa<LoadInst>(I)) { DEBUG(errs() << "\tFound load instruction: " << *I << "\n"); DEBUG(errs() << "\tAdd to use list: " << *V << "\n"); UseList->push_back(V); } - else if(isa<StoreInst>(I)) { + else if(isa<StoreInst>(I) || isa<AtomicRMWInst>(I)) { // found a store in use chain - DEBUG(errs() << "Found store instruction: " << *I << "\n"); + errs() << "Found store/atomicrmw instruction: " << *I << "\n"; + return true; + } + else if(BuildDFG::isViscIntrinsic(I)) { + // If it is an atomic intrinsic, we found a store + IntrinsicInst* II = dyn_cast<IntrinsicInst>(I); + assert(II && II->getCalledValue()->getName().startswith("llvm.visc.atomic") + && "Only visc atomic intrinsics can have an argument as input"); return true; } else { - DEBUG(errs() << "\tTraverse use chain of: " << *I << "\n"); - if(findLoadStoreUses(I, UseList)) + errs() << "\tTraverse use chain of: " << *I << "\n"; + if(findLoadStoreUses(I, UseList, VisitedList)) return true; } } @@ -1762,11 +1780,12 @@ static bool isDependentOnNodeInstanceID(Value* V, std::vector<Value*>*Dependence static bool canBePromoted(Argument* arg, Function* F) { errs() << "OPT: Check if Argument " << *arg << " can be changed to constant memory\n"; std::vector<Value*> UseList; + std::vector<Value*> VisitedList; // recursively traverse use chain // if find a store instruction return false, everything fails, cannot be // promoted // if find a load instruction as use, add the GEP instruction to list - bool foundStore = findLoadStoreUses(arg, &UseList); + bool foundStore = findLoadStoreUses(arg, &UseList, &VisitedList); if(foundStore == true) return false; // See that the GEP instructions are not dependent on getNodeInstanceID @@ -1950,8 +1969,12 @@ static AtomicRMWInst::BinOp getAtomicOp(Intrinsic::ID ID) { return AtomicRMWInst::Sub; case Intrinsic::visc_atomic_min: return AtomicRMWInst::Min; + case Intrinsic::visc_atomic_umin: + return AtomicRMWInst::UMin; case Intrinsic::visc_atomic_max: return AtomicRMWInst::Max; + case Intrinsic::visc_atomic_umax: + return AtomicRMWInst::UMax; //case Intrinsic::visc_atomic_inc: return AtomicRMWInst::Inc; //case Intrinsic::visc_atomic_dec: return AtomicRMWInst::Dec; case Intrinsic::visc_atomic_xchg: diff --git a/llvm/lib/Transforms/GenVISC/GenVISC.cpp b/llvm/lib/Transforms/GenVISC/GenVISC.cpp index 459dd3a721..6e532d457e 100644 --- a/llvm/lib/Transforms/GenVISC/GenVISC.cpp +++ b/llvm/lib/Transforms/GenVISC/GenVISC.cpp @@ -129,6 +129,8 @@ IS_VISC_CALL(atomic_inc) IS_VISC_CALL(atomic_dec) IS_VISC_CALL(atomic_min) IS_VISC_CALL(atomic_max) +IS_VISC_CALL(atomic_umin) +IS_VISC_CALL(atomic_umax) IS_VISC_CALL(atomic_and) IS_VISC_CALL(atomic_or) IS_VISC_CALL(atomic_xor) @@ -1161,9 +1163,15 @@ bool GenVISC::runOnModule(Module &M) { if (isVISCCall_atomic_min(I)) { ReplaceCallWithIntrinsic(I, Intrinsic::visc_atomic_min, &toBeErased); } + if (isVISCCall_atomic_umin(I)) { + ReplaceCallWithIntrinsic(I, Intrinsic::visc_atomic_umin, &toBeErased); + } if (isVISCCall_atomic_max(I)) { ReplaceCallWithIntrinsic(I, Intrinsic::visc_atomic_max, &toBeErased); } + if (isVISCCall_atomic_umax(I)) { + ReplaceCallWithIntrinsic(I, Intrinsic::visc_atomic_umax, &toBeErased); + } if (isVISCCall_atomic_and(I)) { ReplaceCallWithIntrinsic(I, Intrinsic::visc_atomic_and, &toBeErased); } diff --git a/llvm/test/VISC/parboil/common/include/visc.h b/llvm/test/VISC/parboil/common/include/visc.h index 302001348e..29b5be348c 100644 --- a/llvm/test/VISC/parboil/common/include/visc.h +++ b/llvm/test/VISC/parboil/common/include/visc.h @@ -57,6 +57,8 @@ int __visc__atomic_inc(int*); int __visc__atomic_dec(int*); int __visc__atomic_min(int*, int); int __visc__atomic_max(int*, int); +int __visc__atomic_umax(int*, int); +int __visc__atomic_umin(int*, int); int __visc__atomic_and(int*, int); int __visc__atomic_or(int*, int); int __visc__atomic_xor(int*, int); diff --git a/llvm/test/VISC/parboil/datasets/histo/large/input/DESCRIPTION b/llvm/test/VISC/parboil/datasets/histo/large/input/DESCRIPTION index 8942e754cb..87567ca4a5 100755 --- a/llvm/test/VISC/parboil/datasets/histo/large/input/DESCRIPTION +++ b/llvm/test/VISC/parboil/datasets/histo/large/input/DESCRIPTION @@ -1,2 +1,2 @@ Inputs: img.bin -Parameters: -- 1000 4 +Parameters: -- 10000 4 -- GitLab