mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
implement a simple instcombine xform that has been in the
readme forever. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94318 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -237,24 +237,6 @@ define void @test(i32* %P) {
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
dag/inst combine "clz(x)>>5 -> x==0" for 32-bit x.
|
|
||||||
|
|
||||||
Compile:
|
|
||||||
|
|
||||||
int bar(int x)
|
|
||||||
{
|
|
||||||
int t = __builtin_clz(x);
|
|
||||||
return -(t>>5);
|
|
||||||
}
|
|
||||||
|
|
||||||
to:
|
|
||||||
|
|
||||||
_bar: addic r3,r3,-1
|
|
||||||
subfe r3,r3,r3
|
|
||||||
blr
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
quantum_sigma_x in 462.libquantum contains the following loop:
|
quantum_sigma_x in 462.libquantum contains the following loop:
|
||||||
|
|
||||||
for(i=0; i<reg->size; i++)
|
for(i=0; i<reg->size; i++)
|
||||||
@@ -294,6 +276,8 @@ unsigned long reverse(unsigned v) {
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
[LOOP RECOGNITION]
|
||||||
|
|
||||||
These idioms should be recognized as popcount (see PR1488):
|
These idioms should be recognized as popcount (see PR1488):
|
||||||
|
|
||||||
unsigned countbits_slow(unsigned v) {
|
unsigned countbits_slow(unsigned v) {
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "InstCombine.h"
|
#include "InstCombine.h"
|
||||||
|
#include "llvm/IntrinsicInst.h"
|
||||||
#include "llvm/Support/PatternMatch.h"
|
#include "llvm/Support/PatternMatch.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace PatternMatch;
|
using namespace PatternMatch;
|
||||||
@@ -69,11 +70,10 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
|||||||
if (Op1->uge(TypeBits)) {
|
if (Op1->uge(TypeBits)) {
|
||||||
if (I.getOpcode() != Instruction::AShr)
|
if (I.getOpcode() != Instruction::AShr)
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
|
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
|
||||||
else {
|
// ashr i32 X, 32 --> ashr i32 X, 31
|
||||||
I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1));
|
I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1));
|
||||||
return &I;
|
return &I;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ((X*C1) << C2) == (X * (C1 << C2))
|
// ((X*C1) << C2) == (X * (C1 << C2))
|
||||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0))
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0))
|
||||||
@@ -387,7 +387,29 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||||
return commonShiftTransforms(I);
|
if (Instruction *R = commonShiftTransforms(I))
|
||||||
|
return R;
|
||||||
|
|
||||||
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||||
|
|
||||||
|
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1))
|
||||||
|
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
|
||||||
|
// ctlz.i32(x)>>5 --> zext(x == 0)
|
||||||
|
// cttz.i32(x)>>5 --> zext(x == 0)
|
||||||
|
// ctpop.i32(x)>>5 --> zext(x == -1)
|
||||||
|
if ((II->getIntrinsicID() == Intrinsic::ctlz ||
|
||||||
|
II->getIntrinsicID() == Intrinsic::cttz ||
|
||||||
|
II->getIntrinsicID() == Intrinsic::ctpop) &&
|
||||||
|
(1ULL << Op1C->getZExtValue()) ==
|
||||||
|
Op0->getType()->getScalarSizeInBits()) {
|
||||||
|
bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
|
||||||
|
Constant *RHS = ConstantInt::getSigned(Op0->getType(), isCtPop ? -1 : 0);
|
||||||
|
Value *Cmp = Builder->CreateICmpEQ(II->getOperand(1), RHS);
|
||||||
|
return new ZExtInst(Cmp, II->getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
||||||
|
@@ -144,3 +144,18 @@ entry:
|
|||||||
; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
|
; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
|
||||||
; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
|
; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
define i32 @cttz_simplify1(i32 %x) nounwind readnone ssp {
|
||||||
|
%tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x) ; <i32> [#uses=1]
|
||||||
|
%shr3 = lshr i32 %tmp1, 5 ; <i32> [#uses=1]
|
||||||
|
ret i32 %shr3
|
||||||
|
|
||||||
|
; CHECK: @cttz_simplify1
|
||||||
|
; CHECK: icmp eq i32 %x, 0
|
||||||
|
; CHECK-NEXT: zext i1
|
||||||
|
; CHECK-NEXT: ret i32
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @llvm.ctlz.i32(i32) nounwind readnone
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user