Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -74,6 +74,7 @@ void initializeCallGraphWrapperPassPass(PassRegistry &); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); +void initializeBoolRetToIntPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -65,6 +65,7 @@ (void) llvm::createTypeBasedAAWrapperPass(); (void) llvm::createScopedNoAliasAAWrapperPass(); (void) llvm::createBoundsCheckingPass(); + (void) llvm::createBoolRetToIntPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); Index: include/llvm/Transforms/Scalar.h =================================================================== --- include/llvm/Transforms/Scalar.h +++ include/llvm/Transforms/Scalar.h @@ -480,6 +480,12 @@ // FunctionPass *createLoopDistributePass(); +//===----------------------------------------------------------------------===// +// +// BoolRetToInt - Convert i1 to i32 type. +// +Pass *createBoolRetToIntPass(); + } // End llvm namespace #endif Index: lib/Target/PowerPC/PPCTargetMachine.cpp =================================================================== --- lib/Target/PowerPC/PPCTargetMachine.cpp +++ lib/Target/PowerPC/PPCTargetMachine.cpp @@ -282,6 +282,7 @@ } void PPCPassConfig::addIRPasses() { + addPass(createBoolRetToIntPass()); addPass(createAtomicExpandPass(&getPPCTargetMachine())); // For the BG/Q (or if explicitly requested), add explicit data prefetch Index: lib/Transforms/Scalar/BoolRetToInt.cpp =================================================================== --- lib/Transforms/Scalar/BoolRetToInt.cpp +++ lib/Transforms/Scalar/BoolRetToInt.cpp @@ -0,0 +1,114 @@ +#include "llvm/Transforms/Scalar.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Pass.h" + +using namespace llvm; + +namespace { + +class BoolRetToInt : public FunctionPass { + + static ReturnInst *getUniqueRetInst(Function &F) { + ReturnInst *retInst = nullptr; + for (auto &BB : F) { + if (ReturnInst *currRetInst = dyn_cast(BB.getTerminator())) { + if (retInst) return nullptr; + else retInst = currRetInst; + } + } + return retInst; + } + + SetVector findAllDefs(Value *V) { + SetVector defs; + SetVector workList; + workList.insert(V); + while (!workList.empty()) { + Value *curr = workList.back(); + workList.pop_back(); + bool isInserted = defs.insert(curr); + assert(isInserted && "already processed def in worklist?"); + if (User *currUser = dyn_cast(curr)) + for (auto &op : currUser->operands()) + if (!defs.count(op)) + workList.insert(op); + } + return defs; + } + + Value *translate(Value *V) { + Type *int1Ty = Type::getInt1Ty(V->getContext()); + Type *int32Ty = Type::getInt32Ty(V->getContext()); + Value *zero = Constant::getNullValue(int32Ty); + if (Constant *C = dyn_cast(V)) + return ConstantExpr::getZExt(C, int32Ty); + + if (ReturnInst *R = dyn_cast(V)) + return new TruncInst(zero, int1Ty, "backToBool", R); + + if (PHINode *P = dyn_cast(V)) { + PHINode *Q = PHINode::Create(int32Ty, P->getNumIncomingValues(), P->getName(), P); + for (unsigned i = 0; i < P->getNumOperands(); ++i) + Q->addIncoming(zero, P->getIncomingBlock(i)); + return Q; + } + + assert(false && "Unexpected value"); + } + + public: + static char ID; + BoolRetToInt() : FunctionPass(ID) {} + + bool runOnFunction(Function &F) { + + if (!F.getReturnType()->isIntegerTy(1)) + return false; + + ReturnInst *retInst = getUniqueRetInst(F); + if (!retInst) return false; + + SetVector defs = findAllDefs(retInst); + for (auto &V : defs) + if (!isa(V) && !isa(V) && !isa(V)) + return false; + + for (auto &V : defs) + for (auto &W : V->uses()) + if (!defs.count(W)) + return false; + + DenseMap boolToIntMap; + for (auto &V : defs) + boolToIntMap[V] = translate(V); + + for (auto &pair : boolToIntMap) { + User *first = dyn_cast(pair.first); + User *second = dyn_cast(pair.second); + assert (!!first == !!second && "translated from user to non-user!?"); + if (first && second) + for (unsigned i = 0; i < first->getNumOperands(); ++i) + second->setOperand(i, boolToIntMap[first->getOperand(i)]); + } + + retInst->setOperand(0, boolToIntMap[retInst]); + + return true; + } + + void getAnalysisUsage(AnalysisUsage &) const {} +}; + +} + +char BoolRetToInt::ID = 0; +INITIALIZE_PASS(BoolRetToInt, "bool-ret-to-int", + "Convert i1 constants to i32 if they are returned", + false, false) + +Pass *llvm::createBoolRetToIntPass() { + return new BoolRetToInt(); +} Index: lib/Transforms/Scalar/CMakeLists.txt =================================================================== --- lib/Transforms/Scalar/CMakeLists.txt +++ lib/Transforms/Scalar/CMakeLists.txt @@ -2,6 +2,7 @@ ADCE.cpp AlignmentFromAssumptions.cpp BDCE.cpp + BoolRetToInt.cpp ConstantHoisting.cpp ConstantProp.cpp CorrelatedValuePropagation.cpp Index: lib/Transforms/Scalar/Scalar.cpp =================================================================== --- lib/Transforms/Scalar/Scalar.cpp +++ lib/Transforms/Scalar/Scalar.cpp @@ -32,6 +32,8 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeADCEPass(Registry); initializeBDCEPass(Registry); + initializeBoolRetToIntPass(Registry); + initializeEnableShrinkWrapPass(Registry); initializeAlignmentFromAssumptionsPass(Registry); initializeConstantHoistingPass(Registry); initializeConstantPropagationPass(Registry); Index: test/Transforms/BoolRetToInt/BoolRetToIntTest.ll =================================================================== --- test/Transforms/BoolRetToInt/BoolRetToIntTest.ll +++ test/Transforms/BoolRetToInt/BoolRetToIntTest.ll @@ -0,0 +1,55 @@ +; RUN: opt -bool-ret-to-int -S < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-unknown-linux-gnu" + +; Function Attrs: nounwind readnone +; CHECK: i32 @notBoolRet() +define signext i32 @notBoolRet() #0 { +entry: +; CHECK: ret i32 1 + ret i32 1 +} + +; Function Attrs: nounwind +; CHECK: i1 @find +define zeroext i1 @find(i8** readonly %begin, i8** readnone %end, i1 (i8*)* nocapture %hasProp) #1 { +entry: + %cmp.4 = icmp eq i8** %begin, %end + br i1 %cmp.4, label %cleanup, label %for.body.preheader + +for.body.preheader: ; preds = %entry + br label %for.body + +for.cond: ; preds = %for.body + %cmp = icmp eq i8** %incdec.ptr, %end + br i1 %cmp, label %cleanup.loopexit, label %for.body + +for.body: ; preds = %for.body.preheader, %for.cond + %curr.05 = phi i8** [ %incdec.ptr, %for.cond ], [ %begin, %for.body.preheader ] + %0 = load i8*, i8** %curr.05, align 8, !tbaa !1 + %call = tail call zeroext i1 %hasProp(i8* %0) #2 + %incdec.ptr = getelementptr inbounds i8*, i8** %curr.05, i64 1 + br i1 %call, label %cleanup.loopexit, label %for.cond + +cleanup.loopexit: ; preds = %for.body, %for.cond +; CHECK: [[PHI:%.+]] = phi i32 [ 1, %for.body ], [ 0, %for.cond ] + %cleanup.dest.slot.0.ph = phi i1 [ true, %for.body ], [ false, %for.cond ] + br label %cleanup + +cleanup: ; preds = %cleanup.loopexit, %entry +; CHECK: = phi i32 [ 0, %entry ], [ [[PHI]], %cleanup.loopexit ] + %cleanup.dest.slot.0 = phi i1 [ false, %entry ], [ %cleanup.dest.slot.0.ph, %cleanup.loopexit ] +; CHECK: [[REG:%.+]] = trunc i32 {{%.+}} to i1 +; CHECK: ret i1 [[REG]] + ret i1 %cleanup.dest.slot.0 +} + +attributes #0 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+vsx,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+vsx,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!1 = !{!2, !2, i64 0} +!2 = !{!"any pointer", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C/C++ TBAA"}