forked from OSchip/llvm-project
[ConstantHoisting] Remove dupliate logic in constant hoisting
Summary: As metioned in https://reviews.llvm.org/D34576, checkings in `collectConstantCandidates` can be replaced by using `llvm::canReplaceOperandWithVariable`. The only special case is that `collectConstantCandidates` return false for all `IntrinsicInst` but it is safe for us to collect constant candidates from `IntrinsicInst`. Reviewers: pirama, efriedma, srhines Reviewed By: efriedma Subscribers: llvm-commits, javed.absar Differential Revision: https://reviews.llvm.org/D34921 llvm-svn: 307587
This commit is contained in:
parent
a7a77540ef
commit
93abd7d915
|
@ -44,6 +44,7 @@
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Transforms/Scalar.h"
|
#include "llvm/Transforms/Scalar.h"
|
||||||
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -401,42 +402,15 @@ void ConstantHoistingPass::collectConstantCandidates(
|
||||||
if (Inst->isCast())
|
if (Inst->isCast())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Can't handle inline asm. Skip it.
|
|
||||||
if (auto Call = dyn_cast<CallInst>(Inst))
|
|
||||||
if (isa<InlineAsm>(Call->getCalledValue()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Switch cases must remain constant, and if the value being tested is
|
|
||||||
// constant the entire thing should disappear.
|
|
||||||
if (isa<SwitchInst>(Inst))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Static allocas (constant size in the entry block) are handled by
|
|
||||||
// prologue/epilogue insertion so they're free anyway. We definitely don't
|
|
||||||
// want to make them non-constant.
|
|
||||||
auto AI = dyn_cast<AllocaInst>(Inst);
|
|
||||||
if (AI && AI->isStaticAlloca())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Constants in GEPs that index into a struct type should not be hoisted.
|
|
||||||
if (isa<GetElementPtrInst>(Inst)) {
|
|
||||||
gep_type_iterator GTI = gep_type_begin(Inst);
|
|
||||||
|
|
||||||
// Collect constant for first operand.
|
|
||||||
collectConstantCandidates(ConstCandMap, Inst, 0);
|
|
||||||
// Scan rest operands.
|
|
||||||
for (unsigned Idx = 1, E = Inst->getNumOperands(); Idx != E; ++Idx, ++GTI) {
|
|
||||||
// Only collect constants that index into a non struct type.
|
|
||||||
if (!GTI.isStruct()) {
|
|
||||||
collectConstantCandidates(ConstCandMap, Inst, Idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan all operands.
|
// Scan all operands.
|
||||||
for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
|
for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
|
||||||
|
// The cost of materializing the constants (defined in
|
||||||
|
// `TargetTransformInfo::getIntImmCost`) for instructions which only take
|
||||||
|
// constant variables is lower than `TargetTransformInfo::TCC_Basic`. So
|
||||||
|
// it's safe for us to collect constant candidates from all IntrinsicInsts.
|
||||||
|
if (canReplaceOperandWithVariable(Inst, Idx) || isa<IntrinsicInst>(Inst)) {
|
||||||
collectConstantCandidates(ConstCandMap, Inst, Idx);
|
collectConstantCandidates(ConstCandMap, Inst, Idx);
|
||||||
|
}
|
||||||
} // end of for all operands
|
} // end of for all operands
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2169,6 +2169,9 @@ bool llvm::canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx) {
|
||||||
return true;
|
return true;
|
||||||
case Instruction::Call:
|
case Instruction::Call:
|
||||||
case Instruction::Invoke:
|
case Instruction::Invoke:
|
||||||
|
// Can't handle inline asm. Skip it.
|
||||||
|
if (isa<InlineAsm>(ImmutableCallSite(I).getCalledValue()))
|
||||||
|
return false;
|
||||||
// Many arithmetic intrinsics have no issue taking a
|
// Many arithmetic intrinsics have no issue taking a
|
||||||
// variable, however it's hard to distingish these from
|
// variable, however it's hard to distingish these from
|
||||||
// specials such as @llvm.frameaddress that require a constant.
|
// specials such as @llvm.frameaddress that require a constant.
|
||||||
|
|
|
@ -107,3 +107,34 @@ entry:
|
||||||
%ret = add i32 %cast0, %cast1
|
%ret = add i32 %cast0, %cast1
|
||||||
ret i32 %ret
|
ret i32 %ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@exception_type = external global i8
|
||||||
|
|
||||||
|
; Constants in inline ASM should not be hoisted.
|
||||||
|
define i32 @inline_asm_invoke() personality i8* null {
|
||||||
|
;CHECK-LABEL: @inline_asm_invoke
|
||||||
|
;CHECK-NOT: %const = 214672
|
||||||
|
;CHECK: %X = invoke i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
%X = invoke i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
to label %L unwind label %lpad
|
||||||
|
;CHECK: %Y = invoke i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
%Y = invoke i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
to label %L unwind label %lpad
|
||||||
|
L:
|
||||||
|
ret i32 %X
|
||||||
|
lpad:
|
||||||
|
%lp = landingpad i32
|
||||||
|
cleanup
|
||||||
|
catch i8* @exception_type
|
||||||
|
ret i32 1
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @inline_asm_call() {
|
||||||
|
;CHECK-LABEL: @inline_asm_call
|
||||||
|
;CHECK-NOT: %const = 214672
|
||||||
|
;CHECK: %X = call i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
%X = call i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
;CHECK: %Y = call i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
%Y = call i32 asm "bswap $0", "=r,r"(i32 214672)
|
||||||
|
ret i32 %X
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
; RUN: opt -consthoist -S < %s | FileCheck %s
|
||||||
|
target triple = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
%T = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
|
||||||
|
i32, i32, i32, i32, i32, i32 }
|
||||||
|
|
||||||
|
; The second operand of insertvalue is able to be hoisted.
|
||||||
|
define void @test1(%T %P) {
|
||||||
|
; CHECK-LABEL: @test1
|
||||||
|
; CHECK: %const = bitcast i32 256 to i32
|
||||||
|
; CHECK: %1 = insertvalue %T %P, i32 %const, 256
|
||||||
|
; CHECK: %2 = insertvalue %T %P, i32 %const, 256
|
||||||
|
%1 = insertvalue %T %P, i32 256, 256
|
||||||
|
%2 = insertvalue %T %P, i32 256, 256
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
Reference in New Issue