From 01b97dd01eec1197d79fceb7229f5ec233994de3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 23 Nov 2009 16:22:21 +0000 Subject: [PATCH] Make ConstantFoldConstantExpression recursively visit the entire ConstantExpr, not just the top-level operator. This allows it to fold many more constants. Also, make GlobalOpt call ConstantFoldConstantExpression on GlobalVariable initializers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89659 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ConstantFolding.cpp | 13 +++++++++++-- lib/Transforms/IPO/GlobalOpt.cpp | 9 +++++++++ .../GlobalOpt/constantfold-initializers.ll | 8 ++++++++ test/Transforms/InstCombine/cast.ll | 4 ++-- test/Transforms/InstCombine/shufflevec-constant.ll | 2 +- 5 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/Transforms/GlobalOpt/constantfold-initializers.ll diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 1cdadbfcea4..8d60907f8cb 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -671,8 +671,13 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE, const TargetData *TD) { SmallVector Ops; - for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) - Ops.push_back(cast(*i)); + for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) { + Constant *NewC = cast(*i); + // Recursively fold the ConstantExpr's operands. + if (ConstantExpr *NewCE = dyn_cast(NewC)) + NewC = ConstantFoldConstantExpression(NewCE, TD); + Ops.push_back(NewC); + } if (CE->isCompare()) return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], @@ -687,6 +692,10 @@ Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE, /// attempting to fold instructions like loads and stores, which have no /// constant expression form. /// +/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc +/// information, due to only being passed an opcode and operands. Constant +/// folding using this function strips this information. +/// Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, Constant* const* Ops, unsigned NumOps, const TargetData *TD) { diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 442f2fb6552..4635d0e61c3 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -1898,6 +1898,15 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) { // Global variables without names cannot be referenced outside this module. if (!GV->hasName() && !GV->isDeclaration()) GV->setLinkage(GlobalValue::InternalLinkage); + // Simplify the initializer. + if (GV->hasInitializer()) + if (ConstantExpr *CE = dyn_cast(GV->getInitializer())) { + TargetData *TD = getAnalysisIfAvailable(); + Constant *New = ConstantFoldConstantExpression(CE, TD); + if (New && New != CE) + GV->setInitializer(New); + } + // Do more involved optimizations if the global is internal. if (!GV->isConstant() && GV->hasLocalLinkage() && GV->hasInitializer()) Changed |= ProcessInternalGlobal(GV, GVI); diff --git a/test/Transforms/GlobalOpt/constantfold-initializers.ll b/test/Transforms/GlobalOpt/constantfold-initializers.ll new file mode 100644 index 00000000000..834bd0012e7 --- /dev/null +++ b/test/Transforms/GlobalOpt/constantfold-initializers.ll @@ -0,0 +1,8 @@ +; RUN: opt < %s -S -globalopt | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +@.str91250 = global [3 x i8] zeroinitializer + +; CHECK: @A = global i1 false +@A = global i1 icmp ne (i64 sub nsw (i64 ptrtoint (i8* getelementptr inbounds ([3 x i8]* @.str91250, i64 0, i64 1) to i64), i64 ptrtoint ([3 x i8]* @.str91250 to i64)), i64 1) diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index e7695b74b75..5f75cd0a893 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -103,7 +103,7 @@ define i32* @test12() { %p = malloc [4 x i8] ; <[4 x i8]*> [#uses=1] %c = bitcast [4 x i8]* %p to i32* ; [#uses=1] ret i32* %c -; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([4 x i8]* getelementptr ([4 x i8]* null, i32 1) to i32)) +; CHECK: %malloccall = tail call i8* @malloc(i32 4) ; CHECK: ret i32* %c } @@ -275,7 +275,7 @@ define void @test32(double** %tmp) { %tmp8.upgrd.1 = bitcast [16 x i8]* %tmp8 to double* ; [#uses=1] store double* %tmp8.upgrd.1, double** %tmp ret void -; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([16 x i8]* getelementptr ([16 x i8]* null, i32 1) to i32)) +; CHECK: %malloccall = tail call i8* @malloc(i32 16) ; CHECK: %tmp8.upgrd.1 = bitcast i8* %malloccall to double* ; CHECK: store double* %tmp8.upgrd.1, double** %tmp ; CHECK: ret void diff --git a/test/Transforms/InstCombine/shufflevec-constant.ll b/test/Transforms/InstCombine/shufflevec-constant.ll index 2c667903b1e..29ae5a79824 100644 --- a/test/Transforms/InstCombine/shufflevec-constant.ll +++ b/test/Transforms/InstCombine/shufflevec-constant.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep "2 x float" +; RUN: opt < %s -instcombine -S | grep {ret <4 x float> } target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin9"