mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Make GVN look through extractvalues for recognised intrinsics. GVN can then CSE ops that match values produced by the intrinsics.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134677 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0184336195
commit
1fb0955cab
@ -91,6 +91,7 @@ namespace {
|
||||
uint32_t nextValueNumber;
|
||||
|
||||
Expression create_expression(Instruction* I);
|
||||
Expression create_extractvalue_expression(ExtractValueInst* EI);
|
||||
uint32_t lookup_or_add_call(CallInst* C);
|
||||
public:
|
||||
ValueTable() : nextValueNumber(1) { }
|
||||
@ -141,7 +142,6 @@ template <> struct DenseMapInfo<Expression> {
|
||||
// ValueTable Internal Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
Expression ValueTable::create_expression(Instruction *I) {
|
||||
Expression e;
|
||||
e.type = I->getType();
|
||||
@ -150,12 +150,8 @@ Expression ValueTable::create_expression(Instruction *I) {
|
||||
OI != OE; ++OI)
|
||||
e.varargs.push_back(lookup_or_add(*OI));
|
||||
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I))
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I)) {
|
||||
e.opcode = (C->getOpcode() << 8) | C->getPredicate();
|
||||
else if (ExtractValueInst *E = dyn_cast<ExtractValueInst>(I)) {
|
||||
for (ExtractValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end();
|
||||
II != IE; ++II)
|
||||
e.varargs.push_back(*II);
|
||||
} else if (InsertValueInst *E = dyn_cast<InsertValueInst>(I)) {
|
||||
for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end();
|
||||
II != IE; ++II)
|
||||
@ -165,6 +161,55 @@ Expression ValueTable::create_expression(Instruction *I) {
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression ValueTable::create_extractvalue_expression(ExtractValueInst *EI) {
|
||||
assert(EI != 0 && "Not an ExtractValueInst?");
|
||||
Expression e;
|
||||
e.type = EI->getType();
|
||||
e.opcode = 0;
|
||||
|
||||
IntrinsicInst *I = dyn_cast<IntrinsicInst>(EI->getAggregateOperand());
|
||||
if (I != 0 && EI->getNumIndices() == 1 && *EI->idx_begin() == 0 ) {
|
||||
// EI might be an extract from one of our recognised intrinsics. If it
|
||||
// is we'll synthesize a semantically equivalent expression instead on
|
||||
// an extract value expression.
|
||||
switch (I->getIntrinsicID()) {
|
||||
case Intrinsic::uadd_with_overflow:
|
||||
e.opcode = Instruction::Add;
|
||||
break;
|
||||
case Intrinsic::usub_with_overflow:
|
||||
e.opcode = Instruction::Sub;
|
||||
break;
|
||||
case Intrinsic::umul_with_overflow:
|
||||
e.opcode = Instruction::Mul;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (e.opcode != 0) {
|
||||
// Intrinsic recognized. Grab its args to finish building the expression.
|
||||
assert(I->getNumArgOperands() == 2 &&
|
||||
"Expect two args for recognised intrinsics.");
|
||||
e.varargs.push_back(lookup_or_add(I->getArgOperand(0)));
|
||||
e.varargs.push_back(lookup_or_add(I->getArgOperand(1)));
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a recognised intrinsic. Fall back to producing an extract value
|
||||
// expression.
|
||||
e.opcode = EI->getOpcode();
|
||||
for (Instruction::op_iterator OI = EI->op_begin(), OE = EI->op_end();
|
||||
OI != OE; ++OI)
|
||||
e.varargs.push_back(lookup_or_add(*OI));
|
||||
|
||||
for (ExtractValueInst::idx_iterator II = EI->idx_begin(), IE = EI->idx_end();
|
||||
II != IE; ++II)
|
||||
e.varargs.push_back(*II);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ValueTable External Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -336,11 +381,13 @@ uint32_t ValueTable::lookup_or_add(Value *V) {
|
||||
case Instruction::ExtractElement:
|
||||
case Instruction::InsertElement:
|
||||
case Instruction::ShuffleVector:
|
||||
case Instruction::ExtractValue:
|
||||
case Instruction::InsertValue:
|
||||
case Instruction::GetElementPtr:
|
||||
exp = create_expression(I);
|
||||
break;
|
||||
case Instruction::ExtractValue:
|
||||
exp = create_extractvalue_expression(cast<ExtractValueInst>(I));
|
||||
break;
|
||||
default:
|
||||
valueNumbering[V] = nextValueNumber;
|
||||
return nextValueNumber++;
|
||||
|
47
test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll
Normal file
47
test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll
Normal file
@ -0,0 +1,47 @@
|
||||
; RUN: opt < %s -gvn -S | FileCheck %s
|
||||
;
|
||||
|
||||
%0 = type { i64, i1 }
|
||||
|
||||
define i64 @test1(i64 %a, i64 %b) nounwind ssp {
|
||||
entry:
|
||||
%uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
|
||||
%uadd.0 = extractvalue %0 %uadd, 0
|
||||
%add1 = add i64 %a, %b
|
||||
ret i64 %add1
|
||||
}
|
||||
|
||||
; CHECK: @test1
|
||||
; CHECK-NOT: add1
|
||||
; CHECK: ret
|
||||
|
||||
define i64 @test2(i64 %a, i64 %b) nounwind ssp {
|
||||
entry:
|
||||
%usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
|
||||
%usub.0 = extractvalue %0 %usub, 0
|
||||
%sub1 = sub i64 %a, %b
|
||||
ret i64 %sub1
|
||||
}
|
||||
|
||||
; CHECK: @test2
|
||||
; CHECK-NOT: sub1
|
||||
; CHECK: ret
|
||||
|
||||
define i64 @test3(i64 %a, i64 %b) nounwind ssp {
|
||||
entry:
|
||||
%umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
|
||||
%umul.0 = extractvalue %0 %umul, 0
|
||||
%mul1 = mul i64 %a, %b
|
||||
ret i64 %mul1
|
||||
}
|
||||
|
||||
; CHECK: @test3
|
||||
; CHECK-NOT: mul1
|
||||
; CHECK: ret
|
||||
|
||||
|
||||
declare void @exit(i32) noreturn
|
||||
declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
|
||||
declare %0 @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
|
||||
declare %0 @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
|
||||
|
Loading…
Reference in New Issue
Block a user