From 2ac6e2354ac9961b00fa351635ed04baf7fdd234 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 31 Aug 2010 23:00:16 +0000 Subject: [PATCH] licm is wasting time hoisting constant foldable operations, instead of hoisting them, just fold them away. This occurs in the testcase for PR8041, for example. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112669 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LICM.cpp | 20 ++++++++++++++++---- test/Transforms/LICM/hoisting.ll | 16 ++++++++++++++++ test/Transforms/LICM/scalar_promote.ll | 12 ++++++------ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index d3d52f5bb42..fa71ab552c2 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -36,11 +36,11 @@ #include "llvm/DerivedTypes.h" #include "llvm/IntrinsicInst.h" #include "llvm/Instructions.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Transforms/Utils/Local.h" @@ -353,6 +353,18 @@ void LICM::HoistRegion(DomTreeNode *N) { for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ) { Instruction &I = *II++; + // Try constant folding this instruction. If all the operands are + // constants, it is technically hoistable, but it would be better to just + // fold it. + if (Constant *C = ConstantFoldInstruction(&I)) { + DEBUG(dbgs() << "LICM folding inst: " << I << " --> " << *C << '\n'); + CurAST->copyValue(&I, C); + CurAST->deleteValue(&I); + I.replaceAllUsesWith(C); + I.eraseFromParent(); + continue; + } + // Try hoisting the instruction out to the preheader. We can only do this // if all of the operands of the instruction are loop invariant and if it // is safe to hoist the instruction. @@ -360,7 +372,7 @@ void LICM::HoistRegion(DomTreeNode *N) { if (isLoopInvariantInst(I) && canSinkOrHoistInst(I) && isSafeToExecuteUnconditionally(I)) hoist(I); - } + } const std::vector &Children = N->getChildren(); for (unsigned i = 0, e = Children.size(); i != e; ++i) diff --git a/test/Transforms/LICM/hoisting.ll b/test/Transforms/LICM/hoisting.ll index e7d36afb91b..6f28d53af66 100644 --- a/test/Transforms/LICM/hoisting.ll +++ b/test/Transforms/LICM/hoisting.ll @@ -48,3 +48,19 @@ Out: ; preds = %Loop %C = sub i32 %A, %B ; [#uses=1] ret i32 %C } + + +; This loop invariant instruction should be constant folded, not hoisted. +define i32 @test3(i1 %c) { +; CHECK: define i32 @test3 +; CHECK: call void @foo2(i32 6) + %A = load i32* @X ; [#uses=2] + br label %Loop +Loop: + %B = add i32 4, 2 ; [#uses=2] + call void @foo2( i32 %B ) + br i1 %c, label %Loop, label %Out +Out: ; preds = %Loop + %C = sub i32 %A, %B ; [#uses=1] + ret i32 %C +} diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll index ef28c38ca60..6b103f3a1f8 100644 --- a/test/Transforms/LICM/scalar_promote.ll +++ b/test/Transforms/LICM/scalar_promote.ll @@ -1,4 +1,6 @@ ; RUN: opt < %s -licm -S | FileCheck %s +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + @X = global i32 7 ; [#uses=4] define void @test1(i32 %i) { @@ -32,23 +34,21 @@ Entry: br label %Loop ; CHECK: @test2 ; CHECK: Entry: -; CHECK-NEXT: %X1 = getelementptr i32* @X, i64 0 -; CHECK-NEXT: %X2 = getelementptr i32* @X, i64 0 -; CHECK-NEXT: %X1.promoted = load i32* %X1 +; CHECK-NEXT: %.promoted = load i32* getelementptr inbounds (i32* @X, i64 1) ; CHECK-NEXT: br label %Loop Loop: ; preds = %Loop, %0 - %X1 = getelementptr i32* @X, i64 0 ; [#uses=1] + %X1 = getelementptr i32* @X, i64 1 ; [#uses=1] %A = load i32* %X1 ; [#uses=1] %V = add i32 %A, 1 ; [#uses=1] - %X2 = getelementptr i32* @X, i64 0 ; [#uses=1] + %X2 = getelementptr i32* @X, i64 1 ; [#uses=1] store i32 %V, i32* %X2 br i1 false, label %Loop, label %Exit Exit: ; preds = %Loop ret void ; CHECK: Exit: -; CHECK-NEXT: store i32 %V, i32* %X1 +; CHECK-NEXT: store i32 %V, i32* getelementptr inbounds (i32* @X, i64 1) ; CHECK-NEXT: ret void } -- 2.34.1