aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/NaCl/PromoteIntegers.cpp197
-rw-r--r--test/Transforms/NaCl/promote-integers.ll103
2 files changed, 150 insertions, 150 deletions
diff --git a/lib/Transforms/NaCl/PromoteIntegers.cpp b/lib/Transforms/NaCl/PromoteIntegers.cpp
index 97fb08fb55..7ab7beb69a 100644
--- a/lib/Transforms/NaCl/PromoteIntegers.cpp
+++ b/lib/Transforms/NaCl/PromoteIntegers.cpp
@@ -12,16 +12,18 @@
// Legal sizes are currently 1, 8, 16, 32, 64 (and higher, see note below)
// Operations on illegal integers and int pointers are be changed to operate
// on the next-higher legal size.
-// It always maintains the invariant that the upper bits (above the size of the
-// original type) are zero; therefore after operations which can overwrite these
-// bits (e.g. add, shl, sext), the bits are cleared.
+// It maintains no invariants about the upper bits (above the size of the
+// original type); therefore before operations which can be affected by the
+// value of these bits (e.g. cmp, select, lshr), the upper bits of the operands
+// are cleared.
//
// Limitations:
// 1) It can't change function signatures or global variables
// 2) It won't promote (and can't expand) types larger than i64
// 3) Doesn't support div operators
// 4) Doesn't handle arrays or structs (or GEPs) with illegal types
-// 5) Doesn't handle constant expressions
+// 5) Doesn't handle constant expressions (it also doesn't produce them, so it
+// can run after ExpandConstantExpr)
//
//===----------------------------------------------------------------------===//
@@ -303,10 +305,12 @@ static Value *splitStore(StoreInst *Inst, ConversionState &State) {
return StoreHi;
}
-// Return a value with the bits of the operand above the size of the original
-// type cleared. The operand is assumed to have been legalized already.
-static Value *getClearUpper(Value *Operand, Type *OrigType,
- Instruction *InsertPt) {
+// Return a converted value with the bits of the operand above the size of the
+// original type cleared.
+static Value *getClearConverted(Value *Operand, Instruction *InsertPt,
+ ConversionState &State) {
+ Type *OrigType = Operand->getType();
+ Operand = State.getConverted(Operand);
// If the operand is a constant, it will have been created by
// ConversionState.getConverted, which zero-extends by default.
if (isa<Constant>(Operand))
@@ -358,7 +362,7 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
Value *Op = Sext->getOperand(0);
Value *NewInst = NULL;
// If the operand to be extended is illegal, we first need to fill its
- // upper bits (which are zero) with its sign bit.
+ // upper bits with its sign bit.
if (shouldConvert(Op)) {
NewInst = getSignExtend(State.getConverted(Op), Op, Sext);
}
@@ -372,21 +376,13 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
getPromotedType(cast<IntegerType>(Sext->getType())),
Sext->getName() + ".sext", Sext);
}
- // Now all the bits of the result are correct, but we need to restore
- // the bits above its type to zero.
- if (shouldConvert(Sext)) {
- NewInst = getClearUpper(NewInst, Sext->getType(), Sext);
- }
assert(NewInst && "Failed to convert sign extension");
State.recordConverted(Sext, NewInst);
} else if (ZExtInst *Zext = dyn_cast<ZExtInst>(Inst)) {
Value *Op = Zext->getOperand(0);
Value *NewInst = NULL;
- // TODO(dschuff): Some of these zexts could be no-ops.
if (shouldConvert(Op)) {
- NewInst = getClearUpper(State.getConverted(Op),
- Op->getType(),
- Zext);
+ NewInst = getClearConverted(Op, Zext, State);
}
// If the converted type of the operand is the same as the converted
// type of the result, we won't actually be changing the type of the
@@ -402,10 +398,11 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
State.recordConverted(Zext, NewInst);
} else if (TruncInst *Trunc = dyn_cast<TruncInst>(Inst)) {
Value *Op = Trunc->getOperand(0);
- Value *NewInst = NULL;
+ Value *NewInst;
// If the converted type of the operand is the same as the converted
- // type of the result, we won't actually be changing the type of the
- // variable, just its value.
+ // type of the result, we don't actually need to change the type of the
+ // variable, just its value. However, because we don't care about the values
+ // of the upper bits until they are consumed, truncation can be a no-op.
if (getPromotedType(Op->getType()) !=
getPromotedType(Trunc->getType())) {
NewInst = new TruncInst(
@@ -413,15 +410,9 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
getPromotedType(cast<IntegerType>(Trunc->getType())),
State.getConverted(Op)->getName() + ".trunc",
Trunc);
+ } else {
+ NewInst = State.getConverted(Op);
}
- // Restoring the upper-bits-are-zero invariant effectively truncates the
- // value.
- if (shouldConvert(Trunc)) {
- NewInst = getClearUpper(NewInst ? NewInst : Op,
- Trunc->getType(),
- Trunc);
- }
- assert(NewInst);
State.recordConverted(Trunc, NewInst);
} else if (AllocaInst *Alloc = dyn_cast<AllocaInst>(Inst)) {
// Don't handle arrays of illegal types, but we could handle an array
@@ -455,82 +446,74 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
report_fatal_error("can't convert calls with illegal types");
} else if (BinaryOperator *Binop = dyn_cast<BinaryOperator>(Inst)) {
Value *NewInst = NULL;
- if (Binop->getOpcode() == Instruction::AShr) {
- // The AShr operand needs to be sign-extended to the promoted size
- // before shifting. Because the sign-extension is implemented with
- // with AShr, it can be combined with the original operation.
- Value *Op = Binop->getOperand(0);
- Value *ShiftAmount = NULL;
- APInt SignShiftAmt = APInt(
- getPromotedType(Op->getType())->getIntegerBitWidth(),
- getPromotedType(Op->getType())->getIntegerBitWidth() -
- Op->getType()->getIntegerBitWidth());
- NewInst = BinaryOperator::Create(
- Instruction::Shl,
- State.getConverted(Op),
- ConstantInt::get(getPromotedType(Op->getType()), SignShiftAmt),
- State.getConverted(Op)->getName() + ".getsign",
- Binop);
- if (ConstantInt *C = dyn_cast<ConstantInt>(
- State.getConverted(Binop->getOperand(1)))) {
- ShiftAmount = ConstantInt::get(getPromotedType(Op->getType()),
- SignShiftAmt + C->getValue());
- } else {
- ShiftAmount = BinaryOperator::Create(
- Instruction::Add,
- State.getConverted(Binop->getOperand(1)),
- ConstantInt::get(
- getPromotedType(Binop->getOperand(1)->getType()),
- SignShiftAmt),
- State.getConverted(Op)->getName() + ".shamt", Binop);
- }
- NewInst = BinaryOperator::Create(
- Instruction::AShr,
- NewInst,
- ShiftAmount,
- Binop->getName() + ".result", Binop);
- } else {
- // If the original operation is not AShr, just recreate it as usual.
- NewInst = BinaryOperator::Create(
- Binop->getOpcode(),
- State.getConverted(Binop->getOperand(0)),
- State.getConverted(Binop->getOperand(1)),
- Binop->getName() + ".result", Binop);
- if (isa<OverflowingBinaryOperator>(NewInst)) {
- cast<BinaryOperator>(NewInst)->setHasNoUnsignedWrap
- (Binop->hasNoUnsignedWrap());
- cast<BinaryOperator>(NewInst)->setHasNoSignedWrap(
- Binop->hasNoSignedWrap());
+ switch (Binop->getOpcode()) {
+ case Instruction::AShr: {
+ // The AShr operand needs to be sign-extended to the promoted size
+ // before shifting. Because the sign-extension is implemented with
+ // with AShr, it can be combined with the original operation.
+ Value *Op = Binop->getOperand(0);
+ Value *ShiftAmount = NULL;
+ APInt SignShiftAmt = APInt(
+ getPromotedType(Op->getType())->getIntegerBitWidth(),
+ getPromotedType(Op->getType())->getIntegerBitWidth() -
+ Op->getType()->getIntegerBitWidth());
+ NewInst = BinaryOperator::Create(
+ Instruction::Shl,
+ State.getConverted(Op),
+ ConstantInt::get(getPromotedType(Op->getType()), SignShiftAmt),
+ State.getConverted(Op)->getName() + ".getsign",
+ Binop);
+ if (ConstantInt *C = dyn_cast<ConstantInt>(
+ State.getConverted(Binop->getOperand(1)))) {
+ ShiftAmount = ConstantInt::get(getPromotedType(Op->getType()),
+ SignShiftAmt + C->getValue());
+ } else {
+ // Clear the upper bits of the original shift amount, and add back the
+ // amount we shifted to get the sign bit.
+ ShiftAmount = getClearConverted(Binop->getOperand(1), Binop, State);
+ ShiftAmount = BinaryOperator::Create(
+ Instruction::Add,
+ ShiftAmount,
+ ConstantInt::get(
+ getPromotedType(Binop->getOperand(1)->getType()),
+ SignShiftAmt),
+ State.getConverted(Op)->getName() + ".shamt", Binop);
+ }
+ NewInst = BinaryOperator::Create(
+ Instruction::AShr,
+ NewInst,
+ ShiftAmount,
+ Binop->getName() + ".result", Binop);
+ break;
}
- }
- // Now restore the invariant if necessary.
- // This switch also sanity-checks the operation.
- switch (Binop->getOpcode()) {
- case Instruction::And:
- case Instruction::Or:
- case Instruction::Xor:
case Instruction::LShr:
- // These won't change the upper bits.
+ case Instruction::Shl: {
+ // For LShr, clear the upper bits of the operand before shifting them
+ // down into the valid part of the value.
+ Value *Op = Binop->getOpcode() == Instruction::LShr
+ ? getClearConverted(Binop->getOperand(0), Binop, State)
+ : State.getConverted(Binop->getOperand(0));
+ NewInst = BinaryOperator::Create(
+ Binop->getOpcode(), Op,
+ // Clear the upper bits of the shift amount.
+ getClearConverted(Binop->getOperand(1), Binop, State),
+ Binop->getName() + ".result", Binop);
break;
- // These can change the upper bits, unless we are sure they never
- // overflow. So clear them now.
+ }
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
- if (!(Binop->hasNoUnsignedWrap() && Binop->hasNoSignedWrap()))
- NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
- break;
- case Instruction::Shl:
- if (!Binop->hasNoUnsignedWrap())
- NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
- break;
- // We modified the upper bits ourselves when implementing AShr
- case Instruction::AShr:
- NewInst = getClearUpper(NewInst, Binop->getType(), Binop);
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
+ // These operations don't care about the state of the upper bits.
+ NewInst = BinaryOperator::Create(
+ Binop->getOpcode(),
+ State.getConverted(Binop->getOperand(0)),
+ State.getConverted(Binop->getOperand(1)),
+ Binop->getName() + ".result", Binop);
break;
- // We should not see FP operators here.
- // We don't handle div.
case Instruction::FAdd:
case Instruction::FSub:
case Instruction::FMul:
@@ -541,18 +524,25 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
case Instruction::SRem:
case Instruction::FRem:
case Instruction::BinaryOpsEnd:
+ // We should not see FP operators here.
+ // We don't handle div.
errs() << *Inst << "\n";
llvm_unreachable("Cannot handle binary operator");
break;
}
+ if (isa<OverflowingBinaryOperator>(NewInst)) {
+ cast<BinaryOperator>(NewInst)->setHasNoUnsignedWrap(
+ Binop->hasNoUnsignedWrap());
+ cast<BinaryOperator>(NewInst)->setHasNoSignedWrap(
+ Binop->hasNoSignedWrap());
+ }
State.recordConverted(Binop, NewInst);
} else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Inst)) {
Value *Op0, *Op1;
// For signed compares, operands are sign-extended to their
- // promoted type. For unsigned or equality compares, the comparison
- // is equivalent with the larger type because they are already
- // zero-extended.
+ // promoted type. For unsigned or equality compares, the upper bits are
+ // cleared.
if (Cmp->isSigned()) {
Op0 = getSignExtend(State.getConverted(Cmp->getOperand(0)),
Cmp->getOperand(0),
@@ -561,8 +551,8 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
Cmp->getOperand(1),
Cmp);
} else {
- Op0 = State.getConverted(Cmp->getOperand(0));
- Op1 = State.getConverted(Cmp->getOperand(1));
+ Op0 = getClearConverted(Cmp->getOperand(0), Cmp, State);
+ Op1 = getClearConverted(Cmp->getOperand(1), Cmp, State);
}
ICmpInst *NewInst = new ICmpInst(
Cmp, Cmp->getPredicate(), Op0, Op1, "");
@@ -585,8 +575,9 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) {
}
State.recordConverted(Phi, NewPhi);
} else if (SwitchInst *Switch = dyn_cast<SwitchInst>(Inst)) {
+ Value *Condition = getClearConverted(Switch->getCondition(), Switch, State);
SwitchInst *NewInst = SwitchInst::Create(
- State.getConverted(Switch->getCondition()),
+ Condition,
Switch->getDefaultDest(),
Switch->getNumCases(),
Switch);
diff --git a/test/Transforms/NaCl/promote-integers.ll b/test/Transforms/NaCl/promote-integers.ll
index 8d7ebac28e..1067e25fd5 100644
--- a/test/Transforms/NaCl/promote-integers.ll
+++ b/test/Transforms/NaCl/promote-integers.ll
@@ -3,8 +3,7 @@
declare void @consume_i16(i16 %a)
; CHECK: @sext_to_illegal
-; CHECK-NEXT: %a40.sext = sext i32 %a to i64
-; CHECK-NEXT: %a40 = and i64 %a40.sext, 1099511627775
+; CHECK-NEXT: %a40 = sext i32 %a to i64
; (0xFFFFFFFFFF)
define void @sext_to_illegal(i32 %a) {
%a40 = sext i32 %a to i40
@@ -16,21 +15,18 @@ define void @sext_from_illegal(i8 %a) {
; CHECK: call void @consume_i16(i16 -2)
%c12 = sext i12 -2 to i16
call void @consume_i16(i16 %c12)
-; CHECK: %a12.sext = sext i8 %a to i16
-; CHECK-NEXT: %a12 = and i16 %a12.sext, 4095
+; CHECK: %a12 = sext i8 %a to i16
%a12 = sext i8 %a to i12
; CHECK: %a12.getsign = shl i16 %a12, 4
; CHECK-NEXT: %a16 = ashr i16 %a12.getsign, 4
%a16 = sext i12 %a12 to i16
; CHECK: %a12.getsign1 = shl i16 %a12, 4
-; CHECK-NEXT: %a12.signed = ashr i16 %a12.getsign1, 4
-; CHECK-NEXT: %a14 = and i16 %a12.signed, 16383
+; CHECK-NEXT: %a14 = ashr i16 %a12.getsign1, 4
; (0x3FFF)
%a14 = sext i12 %a12 to i14
; CHECK-NEXT: %a12.getsign2 = shl i16 %a12, 4
-; CHECK-NEXT: %a12.signed3 = ashr i16 %a12.getsign2, 4
-; CHECK-NEXT: %a24.sext = sext i16 %a12.signed3 to i32
-; CHECK-NEXT: %a24 = and i32 %a24.sext, 16777215
+; CHECK-NEXT: %a12.signed = ashr i16 %a12.getsign2, 4
+; CHECK-NEXT: %a24 = sext i16 %a12.signed to i32
; (0xFFFFFF)
%a24 = sext i12 %a12 to i24
@@ -56,7 +52,6 @@ define void @zext_from_illegal(i8 %a) {
%a40 = zext i8 %a to i40
%a18 = zext i8 %a to i18
-; TODO(dschuff): the ANDs can be no-ops when we zext from an illegal type.
; CHECK: %a32 = and i32 %a24, 16777215
; (0xFFFFFF)
%a32 = zext i24 %a24 to i32
@@ -79,6 +74,7 @@ define void @zext_from_illegal(i8 %a) {
ret void
}
+; CHECK: @trunc_from_illegal
define void @trunc_from_illegal(i8 %a) {
%a24 = zext i8 %a to i24
; CHECK: %a16 = trunc i32 %a24 to i16
@@ -86,14 +82,15 @@ define void @trunc_from_illegal(i8 %a) {
ret void
}
-define void @trunc_to_illegal(i32 %a) {
-; CHECK: %a24 = and i32 %a, 16777215
-; (0xFFFFFF)
+; CHECK: @trunc_to_illegal
+define void @trunc_to_illegal(i8 %a8) {
+ %a = zext i8 %a8 to i32
+; CHECK-NOT: trunc i32 %a
+; CHECK-NOT: and
%a24 = trunc i32 %a to i24
-; CHECK: %a24.trunc = trunc i32 %a24 to i16
-; CHECK-NEXT: %a12 = and i16 %a24.trunc, 4095
-; (0xFFF)
+; CHECK: %a12 = trunc i32 %a24 to i16
+; CHECK-NOT: and
%a12 = trunc i24 %a24 to i12
ret void
}
@@ -132,9 +129,8 @@ define void @and1(i32 %a) {
; CHECK: @andi3
define void @andi3(i8 %a) {
-; CHECK-NEXT: and i8 %a, 7
%a3 = trunc i8 %a to i3
-; CHECK-NEXT: and i8 %a3, 2
+; CHECK: and i8 %a3, 2
%and = and i3 %a3, 2
ret void
}
@@ -150,37 +146,28 @@ define void @ori7(i8 %a, i8 %b) {
; CHECK: @add1
define void @add1(i16 %a) {
-; CHECK-NEXT: %a24.sext = sext i16 %a to i32
-; CHECK-NEXT: %a24 = and i32 %a24.sext, 16777215
+; CHECK-NEXT: %a24 = sext i16 %a to i32
%a24 = sext i16 %a to i24
-; CHECK-NEXT: %sum.result = add i32 %a24, 16777214
-; CHECK-NEXT: %sum = and i32 %sum.result, 16777215
+; CHECK-NEXT: %sum = add i32 %a24, 16777214
%sum = add i24 %a24, -2
-; CHECK-NEXT: %sumnsw.result = add nsw i32 %a24, 16777214
-; CHECK-NEXT: %sumnsw = and i32 %sumnsw.result, 16777215
+; CHECK-NEXT: %sumnsw = add nsw i32 %a24, 16777214
%sumnsw = add nsw i24 %a24, -2
-; CHECK-NEXT: %sumnuw.result = add nuw i32 %a24, 16777214
-; CHECK-NEXT: %sumnuw = and i32 %sumnuw.result, 16777215
+; CHECK-NEXT: %sumnuw = add nuw i32 %a24, 16777214
%sumnuw = add nuw i24 %a24, -2
; CHECK-NEXT: %sumnw = add nuw nsw i32 %a24, 16777214
-; CHECK-NOT: and
%sumnw = add nuw nsw i24 %a24, -2
ret void
}
; CHECK: @mul1
define void @mul1(i32 %a, i32 %b) {
-; CHECK-NEXT: %a33.sext = sext i32 %a to i64
-; CHECK-NEXT: %a33 = and i64 %a33.sext, 8589934591
+; CHECK-NEXT: %a33 = sext i32 %a to i64
%a33 = sext i32 %a to i33
-; CHECK-NEXT: %b33.sext = sext i32 %b to i64
-; CHECK-NEXT: %b33 = and i64 %b33.sext, 8589934591
+; CHECK-NEXT: %b33 = sext i32 %b to i64
%b33 = sext i32 %b to i33
-; CHECK-NEXT: %product.result = mul i64 %a33, %b33
-; CHECK-NEXT: %product = and i64 %product.result, 8589934591
+; CHECK-NEXT: %product = mul i64 %a33, %b33
%product = mul i33 %a33, %b33
; CHECK-NEXT: %prodnw = mul nuw nsw i64 %a33, %b33
-; CHECK-NOT: and
%prodnw = mul nuw nsw i33 %a33, %b33
ret void
}
@@ -188,9 +175,16 @@ define void @mul1(i32 %a, i32 %b) {
; CHECK: @shl1
define void @shl1(i16 %a) {
%a24 = zext i16 %a to i24
-; CHECK: %ashl.result = shl i32 %a24, 5
-; CHECK: %ashl = and i32 %ashl.result, 16777215
+; CHECK: %ashl = shl i32 %a24, 5
%ashl = shl i24 %a24, 5
+
+; CHECK-NEXT: %ashl2 = shl i32 %a24, 1
+ %ashl2 = shl i24 %a24, 4278190081 ;0xFF000001
+
+ %b24 = zext i16 %a to i24
+; CHECK: %b24.clear = and i32 %b24, 16777215
+; CHECK-NEXT: %bshl = shl i32 %a24, %b24.clear
+ %bshl = shl i24 %a24, %b24
ret void
}
@@ -198,7 +192,6 @@ define void @shl1(i16 %a) {
define void @shlnuw(i16 %a) {
%a12 = trunc i16 %a to i12
; CHECK: %ashl = shl nuw i16 %a12, 5
-; CHECK-NOT: and
%ashl = shl nuw i12 %a12, 5
ret void
}
@@ -206,10 +199,18 @@ define void @shlnuw(i16 %a) {
; CHECK: @lshr1
define void @lshr1(i16 %a) {
%a24 = zext i16 %a to i24
-; CHECK: %b = lshr i32 %a24, 20
+; CHECK: %a24.clear = and i32 %a24, 16777215
+; CHECK-NEXT: %b = lshr i32 %a24.clear, 20
%b = lshr i24 %a24, 20
-; CHECK: %c = lshr i32 %a24, 5
+; CHECK-NEXT: %a24.clear1 = and i32 %a24, 16777215
+; CHECK-NEXT: %c = lshr i32 %a24.clear1, 5
%c = lshr i24 %a24, 5
+
+ %b24 = zext i16 %a to i24
+ %d = lshr i24 %a24, %b24
+; CHECK: %a24.clear2 = and i32 %a24, 16777215
+; CHECK-NEXT: %b24.clear = and i32 %b24, 16777215
+; CHECK-NEXT: %d = lshr i32 %a24.clear2, %b24.clear
ret void
}
@@ -217,13 +218,12 @@ define void @lshr1(i16 %a) {
define void @ashr1(i16 %a) {
%a24 = sext i16 %a to i24
; CHECK: %a24.getsign = shl i32 %a24, 8
-; CHECK-NEXT: %b24.result = ashr i32 %a24.getsign, 19
-; CHECK-NEXT: %b24 = and i32 %b24.result, 16777215
+; CHECK-NEXT: %b24 = ashr i32 %a24.getsign, 19
%b24 = ashr i24 %a24, 11
; CHECK-NEXT: %a24.getsign1 = shl i32 %a24, 8
-; CHECK-NEXT: %a24.shamt = add i32 %b24, 8
-; CHECK-NEXT: %c.result = ashr i32 %a24.getsign1, %a24.shamt
-; CHECK-NEXT: %c = and i32 %c.result, 16777215
+; CHECK-NEXT: %b24.clear = and i32 %b24, 16777215
+; CHECK-NEXT: %a24.shamt = add i32 %b24.clear, 8
+; CHECK-NEXT: %c = ashr i32 %a24.getsign1, %a24.shamt
%c = ashr i24 %a24, %b24
ret void
}
@@ -235,7 +235,8 @@ entry:
loop:
; CHECK: %phi40 = phi i64 [ 1099511627774, %entry ], [ %phi40, %loop ]
%phi40 = phi i40 [ -2, %entry ], [ %phi40, %loop ]
-; CHECK-NEXT: %b = icmp eq i64 %phi40, 1099511627775
+; CHECK-NEXT: %phi40.clear = and i64 %phi40, 1099511627775
+; CHECK-NEXT: %b = icmp eq i64 %phi40.clear, 1099511627775
%b = icmp eq i40 %phi40, -1
; CHECK-NEXT: br i1 %b, label %loop, label %end
br i1 %b, label %loop, label %end
@@ -246,8 +247,15 @@ end:
; CHECK: @icmp_ult
define void @icmp_ult(i32 %a) {
%a40 = zext i32 %a to i40
-; CHECK: %b = icmp ult i64 %a40, 1099511627774
+; CHECK: %a40.clear = and i64 %a40, 1099511627775
+; CHECK-NEXT: %b = icmp ult i64 %a40.clear, 1099511627774
%b = icmp ult i40 %a40, -2
+
+; CHECK: %a40.clear1 = and i64 %a40, 1099511627775
+; CHECK-NEXT: %b40.clear = and i64 %b40, 1099511627775
+; CHECK-NEXT: %c = icmp ult i64 %a40.clear1, %b40.clear
+ %b40 = zext i32 %a to i40
+ %c = icmp ult i40 %a40, %b40
ret void
}
@@ -373,7 +381,8 @@ define void @undefoperand(i32 %a) {
; CHECK: @switch
; CHECK-NEXT: %a24 = zext i16 %a to i32
-; CHECK-NEXT: switch i32 %a24, label %end [
+; CHECK-NEXT: %a24.clear = and i32 %a24, 16777215
+; CHECK-NEXT: switch i32 %a24.clear, label %end [
; CHECK-NEXT: i32 0, label %if1
; CHECK-NEXT: i32 1, label %if2
define void @switch(i16 %a) {