Enhance a bunch of transformations in instcombine to start generating

exact/nsw/nuw shifts and have instcombine infer them when it can prove
that the relevant properties are true for a given shift without them.

Also, a variety of refactoring to use the new patternmatch logic thrown
in for good luck.  I believe that this takes care of a bunch of related
code quality issues attached to PR8862.

llvm-svn: 125267
This commit is contained in:
Chris Lattner 2011-02-10 05:36:31 +00:00
parent 98457101fc
commit 6b657aed33
12 changed files with 197 additions and 161 deletions

View File

@ -19,11 +19,6 @@
using namespace llvm;
using namespace PatternMatch;
/// SubOne - Subtract one from a ConstantInt.
static Constant *SubOne(ConstantInt *C) {
return ConstantInt::get(C->getContext(), C->getValue()-1);
}
/// MultiplyOverflows - True if the multiply can not be expressed in an int
/// this size.
static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) {
@ -57,52 +52,39 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
if (Value *V = SimplifyUsingDistributiveLaws(I))
return ReplaceInstUsesWith(I, V);
// Simplify mul instructions with a constant RHS.
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1C)) {
// ((X << C1)*C2) == (X * (C2 << C1))
if (BinaryOperator *SI = dyn_cast<BinaryOperator>(Op0))
if (SI->getOpcode() == Instruction::Shl)
if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
return BinaryOperator::CreateMul(SI->getOperand(0),
ConstantExpr::getShl(CI, ShOp));
if (CI->isAllOnesValue()) // X * -1 == 0 - X
return BinaryOperator::CreateNeg(Op0, I.getName());
const APInt& Val = cast<ConstantInt>(CI)->getValue();
if (Val.isPowerOf2()) { // Replace X*(2^C) with X << C
return BinaryOperator::CreateShl(Op0,
ConstantInt::get(Op0->getType(), Val.logBase2()));
}
} else if (Op1C->getType()->isVectorTy()) {
if (Op1C->isNullValue())
return ReplaceInstUsesWith(I, Op1C);
if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1C)) {
if (Op1V->isAllOnesValue()) // X * -1 == 0 - X
return BinaryOperator::CreateNeg(Op0, I.getName());
// As above, vector X*splat(1.0) -> X in all defined cases.
if (Constant *Splat = Op1V->getSplatValue()) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(Splat))
if (CI->equalsInt(1))
return ReplaceInstUsesWith(I, Op0);
}
}
if (match(Op1, m_AllOnes())) // X * -1 == 0 - X
return BinaryOperator::CreateNeg(Op0, I.getName());
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
// ((X << C1)*C2) == (X * (C2 << C1))
if (BinaryOperator *SI = dyn_cast<BinaryOperator>(Op0))
if (SI->getOpcode() == Instruction::Shl)
if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
return BinaryOperator::CreateMul(SI->getOperand(0),
ConstantExpr::getShl(CI, ShOp));
const APInt &Val = CI->getValue();
if (Val.isPowerOf2()) { // Replace X*(2^C) with X << C
Constant *NewCst = ConstantInt::get(Op0->getType(), Val.logBase2());
BinaryOperator *Shl = BinaryOperator::CreateShl(Op0, NewCst);
if (I.hasNoSignedWrap()) Shl->setHasNoSignedWrap();
if (I.hasNoUnsignedWrap()) Shl->setHasNoUnsignedWrap();
return Shl;
}
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
if (Op0I->getOpcode() == Instruction::Add && Op0I->hasOneUse() &&
isa<ConstantInt>(Op0I->getOperand(1)) && isa<ConstantInt>(Op1C)) {
// Canonicalize (X+C1)*C2 -> X*C2+C1*C2.
Value *Add = Builder->CreateMul(Op0I->getOperand(0), Op1C, "tmp");
Value *C1C2 = Builder->CreateMul(Op1C, Op0I->getOperand(1));
return BinaryOperator::CreateAdd(Add, C1C2);
// Canonicalize (X+C1)*CI -> X*CI+C1*CI.
{ Value *X; ConstantInt *C1;
if (Op0->hasOneUse() &&
match(Op0, m_Add(m_Value(X), m_ConstantInt(C1)))) {
Value *Add = Builder->CreateMul(X, CI, "tmp");
return BinaryOperator::CreateAdd(Add, Builder->CreateMul(C1, CI));
}
}
}
// Simplify mul instructions with a constant RHS.
if (isa<Constant>(Op1)) {
// Try to fold constant mul into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI))
@ -324,9 +306,8 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
if (MultiplyOverflows(RHS, LHSRHS,
I.getOpcode()==Instruction::SDiv))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
else
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
ConstantExpr::getMul(RHS, LHSRHS));
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
ConstantExpr::getMul(RHS, LHSRHS));
}
if (!RHS->isZero()) { // avoid X udiv 0
@ -365,54 +346,50 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
// X udiv 2^C -> X >> C
// Check to see if this is an unsigned division with an exact power of 2,
// if so, convert to a right shift.
if (C->getValue().isPowerOf2()) // 0 not included in isPowerOf2
return BinaryOperator::CreateLShr(Op0,
if (C->getValue().isPowerOf2()) { // 0 not included in isPowerOf2
BinaryOperator *LShr =
BinaryOperator::CreateLShr(Op0,
ConstantInt::get(Op0->getType(), C->getValue().logBase2()));
if (I.isExact()) LShr->setIsExact();
return LShr;
}
// X udiv C, where C >= signbit
if (C->getValue().isNegative()) {
Value *IC = Builder->CreateICmpULT( Op0, C);
Value *IC = Builder->CreateICmpULT(Op0, C);
return SelectInst::Create(IC, Constant::getNullValue(I.getType()),
ConstantInt::get(I.getType(), 1));
}
}
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
if (BinaryOperator *RHSI = dyn_cast<BinaryOperator>(I.getOperand(1))) {
if (RHSI->getOpcode() == Instruction::Shl &&
isa<ConstantInt>(RHSI->getOperand(0))) {
const APInt& C1 = cast<ConstantInt>(RHSI->getOperand(0))->getValue();
if (C1.isPowerOf2()) {
Value *N = RHSI->getOperand(1);
const Type *NTy = N->getType();
if (uint32_t C2 = C1.logBase2())
N = Builder->CreateAdd(N, ConstantInt::get(NTy, C2), "tmp");
return BinaryOperator::CreateLShr(Op0, N);
}
{ const APInt *CI; Value *N;
if (match(Op1, m_Shl(m_Power2(CI), m_Value(N)))) {
if (*CI != 1)
N = Builder->CreateAdd(N, ConstantInt::get(I.getType(), CI->logBase2()),
"tmp");
if (I.isExact())
return BinaryOperator::CreateExactLShr(Op0, N);
return BinaryOperator::CreateLShr(Op0, N);
}
}
// udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1), (shr X, C2)
// where C1&C2 are powers of two.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
const APInt &TVA = STO->getValue(), &FVA = SFO->getValue();
if (TVA.isPowerOf2() && FVA.isPowerOf2()) {
// Compute the shift amounts
uint32_t TSA = TVA.logBase2(), FSA = FVA.logBase2();
// Construct the "on true" case of the select
Constant *TC = ConstantInt::get(Op0->getType(), TSA);
Value *TSI = Builder->CreateLShr(Op0, TC, SI->getName()+".t");
{ Value *Cond; const APInt *C1, *C2;
if (match(Op1, m_Select(m_Value(Cond), m_Power2(C1), m_Power2(C2)))) {
// Construct the "on true" case of the select
Value *TSI = Builder->CreateLShr(Op0, C1->logBase2(), Op1->getName()+".t",
I.isExact());
// Construct the "on false" case of the select
Constant *FC = ConstantInt::get(Op0->getType(), FSA);
Value *FSI = Builder->CreateLShr(Op0, FC, SI->getName()+".f");
// construct the select instruction and return it.
return SelectInst::Create(SI->getOperand(0), TSI, FSI, SI->getName());
}
}
// Construct the "on false" case of the select
Value *FSI = Builder->CreateLShr(Op0, C2->logBase2(), Op1->getName()+".f",
I.isExact());
// construct the select instruction and return it.
return SelectInst::Create(Cond, TSI, FSI);
}
}
return 0;
}
@ -431,20 +408,17 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
if (RHS->isAllOnesValue())
return BinaryOperator::CreateNeg(Op0);
// sdiv X, C --> ashr X, log2(C)
if (cast<SDivOperator>(&I)->isExact() &&
RHS->getValue().isNonNegative() &&
// sdiv X, C --> ashr exact X, log2(C)
if (I.isExact() && RHS->getValue().isNonNegative() &&
RHS->getValue().isPowerOf2()) {
Value *ShAmt = llvm::ConstantInt::get(RHS->getType(),
RHS->getValue().exactLogBase2());
return BinaryOperator::CreateAShr(Op0, ShAmt, I.getName());
return BinaryOperator::CreateExactAShr(Op0, ShAmt, I.getName());
}
// -X/C --> X/-C provided the negation doesn't overflow.
if (SubOperator *Sub = dyn_cast<SubOperator>(Op0))
if (isa<Constant>(Sub->getOperand(0)) &&
cast<Constant>(Sub->getOperand(0))->isNullValue() &&
Sub->hasNoSignedWrap())
if (match(Sub->getOperand(0), m_Zero()) && Sub->hasNoSignedWrap())
return BinaryOperator::CreateSDiv(Sub->getOperand(1),
ConstantExpr::getNeg(RHS));
}
@ -458,9 +432,8 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
// X sdiv Y -> X udiv Y, iff X and Y don't have sign bit set
return BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
}
ConstantInt *ShiftedInt;
if (match(Op1, m_Shl(m_ConstantInt(ShiftedInt), m_Value())) &&
ShiftedInt->getValue().isPowerOf2()) {
if (match(Op1, m_Shl(m_Power2(), m_Value()))) {
// X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
// Safe because the only negative value (1 << Y) can take on is
// INT_MIN, and X sdiv INT_MIN == X udiv INT_MIN == 0 if X doesn't have
@ -555,43 +528,30 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
if (Instruction *common = commonIRemTransforms(I))
return common;
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// X urem C^2 -> X and C
// Check to see if this is an unsigned remainder with an exact power of 2,
// if so, convert to a bitwise and.
if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
if (C->getValue().isPowerOf2())
return BinaryOperator::CreateAnd(Op0, SubOne(C));
// X urem C^2 -> X and C-1
{ const APInt *C;
if (match(Op1, m_Power2(C)))
return BinaryOperator::CreateAnd(Op0,
ConstantInt::get(I.getType(), *C-1));
}
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
if (RHSI->getOpcode() == Instruction::Shl &&
isa<ConstantInt>(RHSI->getOperand(0))) {
if (cast<ConstantInt>(RHSI->getOperand(0))->getValue().isPowerOf2()) {
Constant *N1 = Constant::getAllOnesValue(I.getType());
Value *Add = Builder->CreateAdd(RHSI, N1, "tmp");
return BinaryOperator::CreateAnd(Op0, Add);
}
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
if (match(Op1, m_Shl(m_Power2(), m_Value()))) {
Constant *N1 = Constant::getAllOnesValue(I.getType());
Value *Add = Builder->CreateAdd(Op1, N1, "tmp");
return BinaryOperator::CreateAnd(Op0, Add);
}
// urem X, (select Cond, 2^C1, 2^C2) -->
// select Cond, (and X, C1-1), (and X, C2-1)
// when C1&C2 are powers of two.
{ Value *Cond; const APInt *C1, *C2;
if (match(Op1, m_Select(m_Value(Cond), m_Power2(C1), m_Power2(C2)))) {
Value *TrueAnd = Builder->CreateAnd(Op0, *C1-1, Op1->getName()+".t");
Value *FalseAnd = Builder->CreateAnd(Op0, *C2-1, Op1->getName()+".f");
return SelectInst::Create(Cond, TrueAnd, FalseAnd);
}
}
// urem X, (select Cond, 2^C1, 2^C2) --> select Cond, (and X, C1), (and X, C2)
// where C1&C2 are powers of two.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
// STO == 0 and SFO == 0 handled above.
if ((STO->getValue().isPowerOf2()) &&
(SFO->getValue().isPowerOf2())) {
Value *TrueAnd = Builder->CreateAnd(Op0, SubOne(STO),
SI->getName()+".t");
Value *FalseAnd = Builder->CreateAnd(Op0, SubOne(SFO),
SI->getName()+".f");
return SelectInst::Create(SI->getOperand(0), TrueAnd, FalseAnd);
}
}
}
return 0;
}

View File

@ -37,17 +37,18 @@ Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
return Res;
// X shift (A srem B) -> X shift (A and B-1) iff B is a power of 2.
// Because shifts by negative values are undefined.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op1))
if (BO->hasOneUse() && BO->getOpcode() == Instruction::SRem)
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->getOperand(1)))
if (CI->getValue().isPowerOf2()) {
Constant *C = ConstantInt::get(BO->getType(), CI->getValue()-1);
Value *Rem = Builder->CreateAnd(BO->getOperand(0), C, BO->getName());
I.setOperand(1, Rem);
return &I;
}
// Because shifts by negative values (which could occur if A were negative)
// are undefined.
Value *A; const APInt *B;
if (Op1->hasOneUse() && match(Op1, m_SRem(m_Value(A), m_Power2(B)))) {
// FIXME: Should this get moved into SimplifyDemandedBits by saying we don't
// demand the sign bit (and many others) here??
Value *Rem = Builder->CreateAnd(A, ConstantInt::get(I.getType(), *B-1),
Op1->getName());
I.setOperand(1, Rem);
return &I;
}
return 0;
}
@ -621,7 +622,30 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
TD))
return ReplaceInstUsesWith(I, V);
return commonShiftTransforms(I);
if (Instruction *V = commonShiftTransforms(I))
return V;
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(I.getOperand(1))) {
unsigned ShAmt = Op1C->getZExtValue();
// If the shifted-out value is known-zero, then this is a NUW shift.
if (!I.hasNoUnsignedWrap() &&
MaskedValueIsZero(I.getOperand(0),
APInt::getHighBitsSet(Op1C->getBitWidth(), ShAmt))) {
I.setHasNoUnsignedWrap();
return &I;
}
// If the shifted out value is all signbits, this is a NSW shift.
if (!I.hasNoSignedWrap() &&
ComputeNumSignBits(I.getOperand(0)) > ShAmt) {
I.setHasNoSignedWrap();
return &I;
}
}
return 0;
}
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
@ -634,7 +658,9 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1))
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
unsigned ShAmt = Op1C->getZExtValue();
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
// ctlz.i32(x)>>5 --> zext(x == 0)
@ -643,7 +669,7 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
if ((II->getIntrinsicID() == Intrinsic::ctlz ||
II->getIntrinsicID() == Intrinsic::cttz ||
II->getIntrinsicID() == Intrinsic::ctpop) &&
isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == Op1C->getZExtValue()){
isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == ShAmt) {
bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
Constant *RHS = ConstantInt::getSigned(Op0->getType(), isCtPop ? -1:0);
Value *Cmp = Builder->CreateICmpEQ(II->getArgOperand(0), RHS);
@ -651,6 +677,14 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
}
}
// If the shifted-out value is known-zero, then this is an exact shift.
if (!I.isExact() &&
MaskedValueIsZero(Op0,APInt::getLowBitsSet(Op1C->getBitWidth(),ShAmt))){
I.setIsExact();
return &I;
}
}
return 0;
}
@ -665,13 +699,15 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
unsigned ShAmt = Op1C->getZExtValue();
// If the input is a SHL by the same constant (ashr (shl X, C), C), then we
// have a sign-extend idiom.
Value *X;
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1)))) {
// If the input value is known to already be sign extended enough, delete
// the extension.
if (ComputeNumSignBits(X) > Op1C->getZExtValue())
// If the left shift is just shifting out partial signbits, delete the
// extension.
if (cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
return ReplaceInstUsesWith(I, X);
// If the input is an extension from the shifted amount value, e.g.
@ -686,6 +722,13 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
return new SExtInst(ZI->getOperand(0), ZI->getType());
}
}
// If the shifted-out value is known-zero, then this is an exact shift.
if (!I.isExact() &&
MaskedValueIsZero(Op0,APInt::getLowBitsSet(Op1C->getBitWidth(),ShAmt))){
I.setIsExact();
return &I;
}
}
// See if we can turn a signed shr into an unsigned shr.

View File

@ -6,7 +6,7 @@ define i64 @test(i64 %X) {
%Y = shl i64 %X, 16 ; <i64> [#uses=1]
; CHECK: %Y = shl i64 %X, 16
%Z = ashr i64 %Y, 16 ; <i64> [#uses=1]
; CHECK: %Z = ashr i64 %Y, 16
; CHECK: %Z = ashr exact i64 %Y, 16
ret i64 %Z
; CHECK: ret i64 %Z
}

View File

@ -1,7 +1,6 @@
; PR1271
; RUN: opt < %s -instcombine -S | \
; RUN: grep {ashr i32 %.mp137, 2}
; END.
; RUN: grep {ashr exact i32 %.mp137, 2}
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"
target triple = "i686-pc-linux-gnu"

View File

@ -452,7 +452,7 @@ define i64 @test48(i8 %A, i8 %a) {
; CHECK: @test48
; CHECK-NEXT: %b = zext i8 %a to i64
; CHECK-NEXT: %B = zext i8 %A to i64
; CHECK-NEXT: %C = shl i64 %B, 8
; CHECK-NEXT: %C = shl nuw nsw i64 %B, 8
; CHECK-NEXT: %D = or i64 %C, %b
; CHECK-NEXT: ret i64 %D
}
@ -464,7 +464,7 @@ define i64 @test49(i64 %A) {
ret i64 %D
; CHECK: @test49
; CHECK-NEXT: %C = shl i64 %A, 32
; CHECK-NEXT: ashr i64 %C, 32
; CHECK-NEXT: ashr exact i64 %C, 32
; CHECK-NEXT: %D = or i64 {{.*}}, 1
; CHECK-NEXT: ret i64 %D
}
@ -478,8 +478,8 @@ define i64 @test50(i64 %A) {
; CHECK: @test50
; CHECK-NEXT: shl i64 %A, 30
; CHECK-NEXT: add i64 {{.*}}, -4294967296
; CHECK-NEXT: %E = ashr i64 {{.*}}, 32
; CHECK-NEXT: ret i64 %E
; CHECK-NEXT: %sext = ashr i64 {{.*}}, 32
; CHECK-NEXT: ret i64 %sext
}
define i64 @test51(i64 %A, i1 %cond) {

View File

@ -7,6 +7,13 @@ define i32 @sdiv1(i32 %x) {
ret i32 %y
}
; CHECK: @sdiv2
; CHECK: ashr exact i32 %x, 3
define i32 @sdiv2(i32 %x) {
%y = sdiv exact i32 %x, 8
ret i32 %y
}
; CHECK: @sdiv3
; CHECK: %y = srem i32 %x, 3
; CHECK: %z = sub i32 %x, %y
@ -52,6 +59,24 @@ define i32 @udiv1(i32 %x, i32 %w) {
ret i32 %z
}
; CHECK: @udiv2
; CHECK: %z = lshr exact i32 %x, %w
; CHECK: ret i32 %z
define i32 @udiv2(i32 %x, i32 %w) {
%y = shl i32 1, %w
%z = udiv exact i32 %x, %y
ret i32 %z
}
; CHECK: @ashr1
; CHECK: %B = ashr exact i64 %A, 2
; CHECK: ret i64 %B
define i64 @ashr1(i64 %X) nounwind {
%A = shl i64 %X, 8
%B = ashr i64 %A, 2 ; X/4
ret i64 %B
}
; CHECK: @ashr_icmp
; CHECK: %B = icmp eq i64 %X, 0
; CHECK: ret i1 %B

View File

@ -28,3 +28,12 @@ define i1 @shl_icmp(i64 %X) nounwind {
ret i1 %B
}
; CHECK: @shl1
; CHECK: %B = shl nuw nsw i64 %A, 8
; CHECK: ret i64 %B
define i64 @shl1(i64 %X, i64* %P) nounwind {
%A = and i64 %X, 312
store i64 %A, i64* %P ; multiple uses of A.
%B = shl i64 %A, 8
ret i64 %B
}

View File

@ -15,7 +15,7 @@ for.cond: ; preds = %for.cond, %codeRepl
store i32 %storemerge, i32* @g_2, align 4
%shl = shl i32 %storemerge, 30
%conv2 = lshr i32 %shl, 24
; CHECK: %0 = shl i32 %storemerge, 6
; CHECK: %0 = shl nuw nsw i32 %storemerge, 6
; CHECK: %conv2 = and i32 %0, 64
%tobool = icmp eq i32 %conv2, 0
br i1 %tobool, label %for.cond, label %codeRepl2

View File

@ -110,7 +110,7 @@ entry:
ret i32 %b
; CHECK: @test10
; CHECK: shl i32 %i, 30
; CHECK-NEXT: ashr i32
; CHECK-NEXT: ashr exact i32
; CHECK-NEXT: ret i32
}

View File

@ -451,7 +451,7 @@ entry:
ret i64 %tmp46
; CHECK: @test37
; CHECK: %tmp23 = shl i128 %tmp22, 32
; CHECK: %tmp23 = shl nuw nsw i128 %tmp22, 32
; CHECK: %ins = or i128 %tmp23, %A
; CHECK: %tmp46 = trunc i128 %ins to i64
}

View File

@ -9,7 +9,7 @@ define i32 @test1(i32 %x) {
ret i32 %tmp.3
; CHECK: @test1
; CHECK: %sext = shl i32 %x, 16
; CHECK: %tmp.3 = ashr i32 %sext, 16
; CHECK: %tmp.3 = ashr exact i32 %sext, 16
; CHECK: ret i32 %tmp.3
}
@ -20,7 +20,7 @@ define i32 @test2(i32 %x) {
ret i32 %tmp.3
; CHECK: @test2
; CHECK: %sext = shl i32 %x, 16
; CHECK: %tmp.3 = ashr i32 %sext, 16
; CHECK: %tmp.3 = ashr exact i32 %sext, 16
; CHECK: ret i32 %tmp.3
}
@ -51,7 +51,7 @@ define i32 @test5(i32 %x) {
ret i32 %tmp.3
; CHECK: @test5
; CHECK: %sext = shl i32 %x, 24
; CHECK: %tmp.3 = ashr i32 %sext, 24
; CHECK: %tmp.3 = ashr exact i32 %sext, 24
; CHECK: ret i32 %tmp.3
}
@ -61,7 +61,7 @@ define i32 @test6(i32 %x) {
ret i32 %tmp.4
; CHECK: @test6
; CHECK: %tmp.2 = shl i32 %x, 16
; CHECK: %tmp.4 = ashr i32 %tmp.2, 16
; CHECK: %tmp.4 = ashr exact i32 %tmp.2, 16
; CHECK: ret i32 %tmp.4
}
@ -82,6 +82,6 @@ entry:
%sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
ret i32 %sub
; CHECK: @test8
; CHECK: %sub = ashr i32 %x, 5
; CHECK: ret i32 %sub
; CHECK: %shr = ashr i32 %x, 5
; CHECK: ret i32 %shr
}

View File

@ -24,7 +24,7 @@ define i64 @test2(i64 %a) {
ret i64 %d
; CHECK: @test2
; CHECK: shl i64 %a, 36
; CHECK: %d = ashr i64 {{.*}}, 36
; CHECK: %d = ashr exact i64 {{.*}}, 36
; CHECK: ret i64 %d
}
define i64 @test3(i64 %a) {
@ -92,7 +92,7 @@ define i64 @test8(i32 %A, i32 %B) {
; CHECK: @test8
; CHECK: %tmp38 = zext i32 %A to i64
; CHECK: %tmp32 = zext i32 %B to i64
; CHECK: %tmp33 = shl i64 %tmp32, 32
; CHECK: %tmp33 = shl nuw i64 %tmp32, 32
; CHECK: %ins35 = or i64 %tmp33, %tmp38
; CHECK: ret i64 %ins35
}