@@ -2743,6 +2743,10 @@ bool GVNPass::processInstruction(Instruction *I) {
27432743 }
27442744 return Changed;
27452745 }
2746+ if (SelectInst *Select = dyn_cast<SelectInst>(I)) {
2747+ if (optimizeMinMaxFindingSelectPattern (Select))
2748+ return true ;
2749+ }
27462750
27472751 // Instructions with void type don't return a value, so there's
27482752 // no point in trying to find redundancies in them.
@@ -3330,6 +3334,124 @@ void GVNPass::assignValNumForDeadCode() {
33303334 }
33313335}
33323336
3337+ bool GVNPass::optimizeMinMaxFindingSelectPattern (SelectInst *Select) {
3338+ LLVM_DEBUG (
3339+ dbgs ()
3340+ << " GVN: Analyzing select instruction for minimum finding pattern\n " );
3341+ LLVM_DEBUG (dbgs () << " GVN: Select: " << *Select << " \n " );
3342+ Value *Condition = Select->getCondition ();
3343+ CmpInst *Comparison = dyn_cast<CmpInst>(Condition);
3344+ if (!Comparison) {
3345+ LLVM_DEBUG (dbgs () << " GVN: Condition is not a comparison\n " );
3346+ return false ;
3347+ }
3348+
3349+ // Check if this is ULT comparison.
3350+ CmpInst::Predicate Pred = Comparison->getPredicate ();
3351+ if (Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_ULT &&
3352+ Pred != CmpInst::FCMP_OLT && Pred != CmpInst::FCMP_ULT) {
3353+ LLVM_DEBUG (dbgs () << " GVN: Not a less-than comparison, predicate: " << Pred
3354+ << " \n " );
3355+ return false ;
3356+ }
3357+
3358+ // Check that both operands are loads.
3359+ Value *LHS = Comparison->getOperand (0 );
3360+ Value *RHS = Comparison->getOperand (1 );
3361+ if (!isa<LoadInst>(LHS) || !isa<LoadInst>(RHS)) {
3362+ LLVM_DEBUG (dbgs () << " GVN: Not both operands are loads\n " );
3363+ return false ;
3364+ }
3365+
3366+ LLVM_DEBUG (dbgs () << " GVN: Found minimum finding pattern in Block: "
3367+ << Select->getParent ()->getName () << " \n " );
3368+
3369+ // Transform the pattern.
3370+ // Hoist the chain of operations for the second load to preheader.
3371+ // Get predecessor of the block containing the select instruction.
3372+ BasicBlock *BB = Select->getParent ();
3373+
3374+ // Get preheader of the loop.
3375+ Loop *L = LI->getLoopFor (BB);
3376+ if (!L) {
3377+ LLVM_DEBUG (dbgs () << " GVN: Could not find loop\n " );
3378+ return false ;
3379+ }
3380+ BasicBlock *Preheader = L->getLoopPreheader ();
3381+ if (!Preheader) {
3382+ LLVM_DEBUG (dbgs () << " GVN: Could not find loop preheader\n " );
3383+ return false ;
3384+ }
3385+
3386+ // Hoist the chain of operations for the second load to preheader.
3387+ // %90 = sext i32 %.05.i to i64
3388+ // %91 = getelementptr float, ptr %0, i64 %90 ; %0 + (sext i32 %85 to i64)*4
3389+ // %92 = getelementptr i8, ptr %91, i64 -4 ; %0 + (sext i32 %85 to i64)*4 - 4
3390+ // %93 = load float, ptr %92, align 4
3391+
3392+ Value *BasePtr = nullptr , *IndexVal = nullptr , *OffsetVal = nullptr ;
3393+ IRBuilder<> Builder (Preheader->getTerminator ());
3394+ if (match (RHS,
3395+ m_Load (m_GEP (m_GEP (m_Value (BasePtr), m_SExt (m_Value (IndexVal))),
3396+ m_Value (OffsetVal))))) {
3397+ LLVM_DEBUG (dbgs () << " GVN: Found pattern: " << *RHS << " \n " );
3398+ LLVM_DEBUG (dbgs () << " GVN: Found pattern: " << " \n " );
3399+
3400+ PHINode *Phi = dyn_cast<PHINode>(IndexVal);
3401+ if (!Phi) {
3402+ LLVM_DEBUG (dbgs () << " GVN: IndexVal is not a PHI node\n " );
3403+ return false ;
3404+ }
3405+ Value *InitialMinIndex = Phi->getIncomingValueForBlock (Preheader);
3406+
3407+ // Insert PHI node at the top of this block.
3408+ PHINode *KnownMinPhi =
3409+ PHINode::Create (Builder.getFloatTy (), 2 , " known_min" , BB->begin ());
3410+
3411+ // Build the GEP chain in the preheader.
3412+ // 1. hoist_0 = sext i32 to i64
3413+ Value *HoistedSExt =
3414+ Builder.CreateSExt (InitialMinIndex, Builder.getInt64Ty (), " hoist_sext" );
3415+
3416+ // 2. hoist_gep1 = getelementptr float, ptr BasePtr, i64 HoistedSExt
3417+ Value *HoistedGEP1 = Builder.CreateGEP (Builder.getFloatTy (), BasePtr,
3418+ HoistedSExt, " hoist_gep1" );
3419+
3420+ // 3. hoist_gep2 = getelementptr i8, ptr HoistedGEP1, i64 OffsetVal
3421+ Value *HoistedGEP2 = Builder.CreateGEP (Builder.getInt8Ty (), HoistedGEP1,
3422+ OffsetVal, " hoist_gep2" );
3423+
3424+ // 4. hoisted_load = load float, ptr HoistedGEP2
3425+ LoadInst *NewLoad =
3426+ Builder.CreateLoad (Builder.getFloatTy (), HoistedGEP2, " hoisted_load" );
3427+
3428+ // Replace all uses of load with new load.
3429+ RHS->replaceAllUsesWith (NewLoad);
3430+ dyn_cast<LoadInst>(RHS)->eraseFromParent ();
3431+
3432+ // Replace second operand of comparison with KnownMinPhi.
3433+ Comparison->setOperand (1 , KnownMinPhi);
3434+
3435+ // Create new select instruction for selecting the minimum value.
3436+ IRBuilder<> SelectBuilder (BB->getTerminator ());
3437+ SelectInst *CurrentMinSelect =
3438+ dyn_cast<SelectInst>(SelectBuilder.CreateSelect (
3439+ Comparison, LHS, KnownMinPhi, " current_min" ));
3440+
3441+ // Populate PHI node.
3442+ KnownMinPhi->addIncoming (NewLoad, Preheader);
3443+ KnownMinPhi->addIncoming (CurrentMinSelect, BB);
3444+ LLVM_DEBUG (dbgs () << " Transformed the code\n " );
3445+ return true ;
3446+ } else {
3447+ LLVM_DEBUG (dbgs () << " GVN: Could not find pattern: " << *RHS << " \n " );
3448+ LLVM_DEBUG (dbgs () << " GVN: Could not find pattern: " << " \n " );
3449+ return false ;
3450+ }
3451+ return false ;
3452+ }
3453+
3454+
33333455class llvm ::gvn::GVNLegacyPass : public FunctionPass {
33343456public:
33353457 static char ID; // Pass identification, replacement for typeid.
0 commit comments