3030#include < llvm/IR/Dominators.h>
3131#include < llvm/IR/IRBuilder.h>
3232#include < llvm/Support/Debug.h>
33+ #include < llvm/Support/Error.h>
3334#include < llvm/Support/raw_ostream.h>
3435
3536#include < queue>
@@ -145,17 +146,19 @@ class ControlFlowConversionState::Impl : public ControlFlowConversionState {
145146 // / @brief Apply masks to basic blocks in the function, to prevent
146147 // / side-effects for inactive instances.
147148 // /
148- // / @return true if masks were applied successfully, false otherwise.
149- bool applyMasks ();
149+ // / @return llvm::Error::success if masks were applied successfully, an error
150+ // / message explaining the failure otherwise.
151+ Error applyMasks ();
150152
151153 // / @brief Apply a mask to the given basic block, to prevent side-effects for
152154 // / inactive instances.
153155 // /
154156 // / @param[in] BB Basic block to apply masks to.
155157 // / @param[in] mask Mask to apply.
156158 // /
157- // / @return true if masks were applied successfully, false otherwise.
158- bool applyMask (BasicBlock &BB, Value *mask);
159+ // / @return llvm::Error::success if masks were applied successfully, an error
160+ // / message explaining the failure otherwise.
161+ Error applyMask (BasicBlock &BB, Value *mask);
159162
160163 // / @brief Emit a call instructions to the masked version of the called
161164 // / function.
@@ -378,6 +381,14 @@ Instruction *copyExitMask(Value *mask, StringRef base, BasicBlock &BB) {
378381 VECZ_ERROR_IF (!mask, " Trying to copy exit mask with invalid arguments" );
379382 return copyMask (mask, base + " .exit_mask" , BB.getTerminator ());
380383}
384+
385+ // / Wrap a string into an llvm::StringError, pointing to an instruction.
386+ static inline Error makeStringError (const Twine &message, Instruction &I) {
387+ std::string helper_str = message.str ();
388+ raw_string_ostream helper_stream (helper_str);
389+ helper_stream << " " << I;
390+ return make_error<StringError>(helper_stream.str (), inconvertibleErrorCode ());
391+ }
381392} // namespace
382393
383394// //////////////////////////////////////////////////////////////////////////////
@@ -538,8 +549,9 @@ bool ControlFlowConversionState::Impl::convertToDataFlow() {
538549 " Could not generate masks for" );
539550 return false ;
540551 }
541- if (!applyMasks ()) {
542- emitVeczRemarkMissed (&F, VU.scalarFunction (), " Could not apply masks for" );
552+ if (auto err = applyMasks ()) {
553+ emitVeczRemarkMissed (&F, VU.scalarFunction (), " Could not apply masks for" ,
554+ llvm::toString (std::move (err)));
543555 return false ;
544556 }
545557
@@ -1075,19 +1087,21 @@ bool ControlFlowConversionState::Impl::createCombinedLoopExitMask(
10751087 return true ;
10761088}
10771089
1078- bool ControlFlowConversionState::Impl::applyMasks () {
1090+ Error ControlFlowConversionState::Impl::applyMasks () {
10791091 for (auto &BB : F) {
10801092 // Use masks with instructions that have side-effects.
10811093 if (!DR->isUniform (BB) && !DR->isByAll (BB)) {
10821094 auto *const entryMask = MaskInfos[&BB].entryMask ;
10831095 VECZ_ERROR_IF (!entryMask, " BasicBlock should have an entry mask" );
1084- VECZ_FAIL_IF (!applyMask (BB, entryMask));
1096+ if (auto err = applyMask (BB, entryMask)) {
1097+ return err;
1098+ }
10851099 }
10861100 }
1087- return true ;
1101+ return Error::success () ;
10881102}
10891103
1090- bool ControlFlowConversionState::Impl::applyMask (BasicBlock &BB, Value *mask) {
1104+ Error ControlFlowConversionState::Impl::applyMask (BasicBlock &BB, Value *mask) {
10911105 // Packetization hasn't happened yet so this better be a scalar 1 bit int.
10921106 assert (mask->getType ()->isIntegerTy (1 ) && " CFG mask type should be int1" );
10931107 // Map the unmasked instruction with the masked one.
@@ -1102,17 +1116,17 @@ bool ControlFlowConversionState::Impl::applyMask(BasicBlock &BB, Value *mask) {
11021116 // Turn loads and stores into masked loads and stores.
11031117 if (memOp && (memOp->isLoad () || memOp->isStore ())) {
11041118 if (!tryApplyMaskToMemOp (*memOp, mask, toDelete)) {
1105- return false ;
1119+ return makeStringError ( " Could not apply mask to MemOp " , I) ;
11061120 }
11071121 } else if (auto *CI = dyn_cast<CallInst>(&I)) {
11081122 // Turn calls into masked calls if possible.
11091123 if (!applyMaskToCall (CI, mask, toDelete)) {
1110- return false ;
1124+ return makeStringError ( " Could not apply mask to call instruction " , I) ;
11111125 }
11121126 } else if (I.isAtomic () && !isa<FenceInst>(&I)) {
11131127 // We need to apply masks to atomic functions, but it is currently not
11141128 // implemented. See CA-3294.
1115- return false ;
1129+ return makeStringError ( " Could not apply mask to atomic instruction " , I) ;
11161130 } else if (auto *branch = dyn_cast<BranchInst>(&I)) {
11171131 // We have to be careful with infinite loops, because if they exist on a
11181132 // divergent code path, they will always be entered and will hang the
@@ -1138,7 +1152,8 @@ bool ControlFlowConversionState::Impl::applyMask(BasicBlock &BB, Value *mask) {
11381152 updateMaps (unmasked, masked);
11391153 IRCleanup::deleteInstructionNow (unmasked);
11401154 }
1141- return true ;
1155+
1156+ return Error::success ();
11421157}
11431158
11441159CallInst *ControlFlowConversionState::Impl::emitMaskedVersion (CallInst *CI,
0 commit comments