[llvm] 355ee18 - [TypePromotion] Extend TypePromotion::isSafeWrap
David Green via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 14 03:18:36 PST 2021
Author: David Green
Date: 2021-11-14T11:18:31Z
New Revision: 355ee18c5df9364f315f2bfad1793dd54efe6c9b
URL: https://github.com/llvm/llvm-project/commit/355ee18c5df9364f315f2bfad1793dd54efe6c9b
DIFF: https://github.com/llvm/llvm-project/commit/355ee18c5df9364f315f2bfad1793dd54efe6c9b.diff
LOG: [TypePromotion] Extend TypePromotion::isSafeWrap
This modifies the preconditions of TypePromotion's isSafeWrap
method, to allow it to work from all constants from the ICmp.
Using the code:
%a = add %x, C1
%c = icmp ult %a, C2
According to Alive, we can prove that is equivalent to
icmp ult (add zext(%x), sext(C1)), zext(C2) given
C1 <=s 0 and C1 >s C2.
https://alive2.llvm.org/ce/z/CECYZB
Which is similar to what is already present. We can also
prove icmp ult (add zext(%x), sext(C1)), sext(C2) given
C1 <=s 0 and C1 <=s C2.
https://alive2.llvm.org/ce/z/KKgyeL
The PrepareWrappingAdds method was removed, and the
constants are now altered to sext or zext directly as
required by the above methods.
Differential Revision: https://reviews.llvm.org/D113678
Added:
Modified:
llvm/lib/CodeGen/TypePromotion.cpp
llvm/test/CodeGen/AArch64/and-mask-removal.ll
llvm/test/CodeGen/AArch64/typepromotion-overflow.ll
llvm/test/Transforms/TypePromotion/ARM/casts.ll
llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
llvm/test/Transforms/TypePromotion/ARM/icmps.ll
llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp
index 782d7eed27a68..d042deefd746a 100644
--- a/llvm/lib/CodeGen/TypePromotion.cpp
+++ b/llvm/lib/CodeGen/TypePromotion.cpp
@@ -108,7 +108,7 @@ class IRPromoter {
SetVector<Value*> &Visited;
SetVector<Value*> &Sources;
SetVector<Instruction*> &Sinks;
- SmallVectorImpl<Instruction*> &SafeWrap;
+ SmallPtrSetImpl<Instruction *> &SafeWrap;
IntegerType *ExtTy = nullptr;
SmallPtrSet<Value*, 8> NewInsts;
SmallPtrSet<Instruction*, 4> InstsToRemove;
@@ -116,7 +116,6 @@ class IRPromoter {
SmallPtrSet<Value*, 8> Promoted;
void ReplaceAllUsersOfWith(Value *From, Value *To);
- void PrepareWrappingAdds(void);
void ExtendSources(void);
void ConvertTruncs(void);
void PromoteTree(void);
@@ -125,11 +124,11 @@ class IRPromoter {
public:
IRPromoter(LLVMContext &C, IntegerType *Ty, unsigned Width,
- SetVector<Value*> &visited, SetVector<Value*> &sources,
- SetVector<Instruction*> &sinks,
- SmallVectorImpl<Instruction*> &wrap) :
- Ctx(C), OrigTy(Ty), PromotedWidth(Width), Visited(visited),
- Sources(sources), Sinks(sinks), SafeWrap(wrap) {
+ SetVector<Value *> &visited, SetVector<Value *> &sources,
+ SetVector<Instruction *> &sinks,
+ SmallPtrSetImpl<Instruction *> &wrap)
+ : Ctx(C), OrigTy(Ty), PromotedWidth(Width), Visited(visited),
+ Sources(sources), Sinks(sinks), SafeWrap(wrap) {
ExtTy = IntegerType::get(Ctx, PromotedWidth);
assert(OrigTy->getPrimitiveSizeInBits().getFixedSize() <
ExtTy->getPrimitiveSizeInBits().getFixedSize() &&
@@ -145,7 +144,7 @@ class TypePromotion : public FunctionPass {
unsigned RegisterBitWidth = 0;
SmallPtrSet<Value*, 16> AllVisited;
SmallPtrSet<Instruction*, 8> SafeToPromote;
- SmallVector<Instruction*, 4> SafeWrap;
+ SmallPtrSet<Instruction *, 4> SafeWrap;
// Does V have the same size result type as TypeSize.
bool EqualTypeSize(Value *V);
@@ -333,44 +332,46 @@ bool TypePromotion::isSafeWrap(Instruction *I) {
if (Opc != Instruction::Add && Opc != Instruction::Sub)
return false;
- if (!I->hasOneUse() ||
- !isa<ICmpInst>(*I->user_begin()) ||
+ if (!I->hasOneUse() || !isa<ICmpInst>(*I->user_begin()) ||
!isa<ConstantInt>(I->getOperand(1)))
return false;
- ConstantInt *OverflowConst = cast<ConstantInt>(I->getOperand(1));
- bool NegImm = OverflowConst->isNegative();
- bool IsDecreasing = ((Opc == Instruction::Sub) && !NegImm) ||
- ((Opc == Instruction::Add) && NegImm);
- if (!IsDecreasing)
- return false;
-
// Don't support an icmp that deals with sign bits.
auto *CI = cast<ICmpInst>(*I->user_begin());
if (CI->isSigned() || CI->isEquality())
return false;
- ConstantInt *ICmpConst = nullptr;
+ ConstantInt *ICmpConstant = nullptr;
if (auto *Const = dyn_cast<ConstantInt>(CI->getOperand(0)))
- ICmpConst = Const;
+ ICmpConstant = Const;
else if (auto *Const = dyn_cast<ConstantInt>(CI->getOperand(1)))
- ICmpConst = Const;
+ ICmpConstant = Const;
else
return false;
- // Now check that the result can't wrap on itself.
- APInt Total = ICmpConst->getValue().zextOrSelf(RegisterBitWidth);
- Total += OverflowConst->getValue().abs().zextOrSelf(RegisterBitWidth);
-
- APInt Max = APInt::getAllOnes(TypeSize).zextOrSelf(RegisterBitWidth);
-
- if (Total.ugt(Max))
+ const APInt &ICmpConst = ICmpConstant->getValue();
+ APInt OverflowConst = cast<ConstantInt>(I->getOperand(1))->getValue();
+ if (Opc == Instruction::Sub)
+ OverflowConst = -OverflowConst;
+ if (!OverflowConst.isNonPositive())
return false;
- LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for " << *I
- << "\n");
- SafeWrap.push_back(I);
- return true;
+ // Using C1 = OverflowConst and C2 = ICmpConst, we can use either prove that:
+ // zext(x) + sext(C1) <u zext(C2) if C1 < 0 and C1 >s C2
+ // zext(x) + sext(C1) <u sext(C2) if C1 < 0 and C1 <=s C2
+ if (OverflowConst.sgt(ICmpConst)) {
+ LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for sext "
+ << "const of " << *I << "\n");
+ SafeWrap.insert(I);
+ return true;
+ } else {
+ LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for sext "
+ << "const of " << *I << " and " << *CI << "\n");
+ SafeWrap.insert(I);
+ SafeWrap.insert(CI);
+ return true;
+ }
+ return false;
}
bool TypePromotion::shouldPromote(Value *V) {
@@ -408,7 +409,7 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
bool ReplacedAll = true;
LLVM_DEBUG(dbgs() << "IR Promotion: Replacing " << *From << " with " << *To
- << "\n");
+ << "\n");
for (Use &U : From->uses()) {
auto *User = cast<Instruction>(U.getUser());
@@ -427,39 +428,6 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
InstsToRemove.insert(I);
}
-void IRPromoter::PrepareWrappingAdds() {
- LLVM_DEBUG(dbgs() << "IR Promotion: Prepare wrapping adds.\n");
- IRBuilder<> Builder{Ctx};
-
- // For adds that safely wrap and use a negative immediate as operand 1, we
- // create an equivalent instruction using a positive immediate.
- // That positive immediate can then be zext along with all the other
- // immediates later.
- for (auto *I : SafeWrap) {
- if (I->getOpcode() != Instruction::Add)
- continue;
-
- LLVM_DEBUG(dbgs() << "IR Promotion: Adjusting " << *I << "\n");
- assert((isa<ConstantInt>(I->getOperand(1)) &&
- cast<ConstantInt>(I->getOperand(1))->isNegative()) &&
- "Wrapping should have a negative immediate as the second operand");
-
- auto Const = cast<ConstantInt>(I->getOperand(1));
- auto *NewConst = ConstantInt::get(Ctx, Const->getValue().abs());
- Builder.SetInsertPoint(I);
- Value *NewVal = Builder.CreateSub(I->getOperand(0), NewConst);
- if (auto *NewInst = dyn_cast<Instruction>(NewVal)) {
- NewInst->copyIRFlags(I);
- NewInsts.insert(NewInst);
- }
- InstsToRemove.insert(I);
- I->replaceAllUsesWith(NewVal);
- LLVM_DEBUG(dbgs() << "IR Promotion: New equivalent: " << *NewVal << "\n");
- }
- for (auto *I : NewInsts)
- Visited.insert(I);
-}
-
void IRPromoter::ExtendSources() {
IRBuilder<> Builder{Ctx};
@@ -517,7 +485,9 @@ void IRPromoter::PromoteTree() {
continue;
if (auto *Const = dyn_cast<ConstantInt>(Op)) {
- Constant *NewConst = ConstantExpr::getZExt(Const, ExtTy);
+ Constant *NewConst = SafeWrap.contains(I)
+ ? ConstantExpr::getSExt(Const, ExtTy)
+ : ConstantExpr::getZExt(Const, ExtTy);
I->setOperand(i, NewConst);
} else if (isa<UndefValue>(Op))
I->setOperand(i, UndefValue::get(ExtTy));
@@ -678,10 +648,6 @@ void IRPromoter::Mutate() {
TruncTysMap[Trunc].push_back(Trunc->getDestTy());
}
- // Convert adds using negative immediates to equivalent instructions that use
- // positive constants.
- PrepareWrappingAdds();
-
// Insert zext instructions between sources and their users.
ExtendSources();
@@ -797,7 +763,7 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) {
return false;
LLVM_DEBUG(dbgs() << "IR Promotion: TryToPromote: " << *V << ", from "
- << TypeSize << " bits to " << PromotedWidth << "\n");
+ << TypeSize << " bits to " << PromotedWidth << "\n");
SetVector<Value*> WorkList;
SetVector<Value*> Sources;
diff --git a/llvm/test/CodeGen/AArch64/and-mask-removal.ll b/llvm/test/CodeGen/AArch64/and-mask-removal.ll
index d486aba9c04ff..bd88815a88d3b 100644
--- a/llvm/test/CodeGen/AArch64/and-mask-removal.ll
+++ b/llvm/test/CodeGen/AArch64/and-mask-removal.ll
@@ -131,8 +131,7 @@ define zeroext i1 @test8_5(i8 zeroext %x) align 2 {
; CHECK-LABEL: test8_5:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: sub w8, w0, #123
-; CHECK-NEXT: and w8, w8, #0xff
-; CHECK-NEXT: cmp w8, #150
+; CHECK-NEXT: cmn w8, #106
; CHECK-NEXT: cset w0, hi
; CHECK-NEXT: ret
entry:
diff --git a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll
index f06a0b3bf240b..c9fb0dd1461f7 100644
--- a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll
+++ b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll
@@ -173,13 +173,13 @@ define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
ret i32 %res
}
-define i32 @unsafe_sub_underflow(i8 zeroext %a) {
-; CHECK-LABEL: unsafe_sub_underflow:
+; This is valid so long as the icmp immediate is sext.
+define i32 @sext_sub_underflow(i8 zeroext %a) {
+; CHECK-LABEL: sext_sub_underflow:
; CHECK: // %bb.0:
; CHECK-NEXT: sub w9, w0, #6
; CHECK-NEXT: mov w8, #16
-; CHECK-NEXT: and w9, w9, #0xff
-; CHECK-NEXT: cmp w9, #250
+; CHECK-NEXT: cmn w9, #6
; CHECK-NEXT: mov w9, #8
; CHECK-NEXT: csel w0, w9, w8, hi
; CHECK-NEXT: ret
@@ -217,13 +217,13 @@ define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
ret i32 %res
}
-define i32 @unsafe_sub_underflow_neg(i8 zeroext %a) {
-; CHECK-LABEL: unsafe_sub_underflow_neg:
+; This is valid so long as the icmp immediate is sext.
+define i32 @sext_sub_underflow_neg(i8 zeroext %a) {
+; CHECK-LABEL: sext_sub_underflow_neg:
; CHECK: // %bb.0:
; CHECK-NEXT: sub w9, w0, #4
; CHECK-NEXT: mov w8, #16
-; CHECK-NEXT: and w9, w9, #0xff
-; CHECK-NEXT: cmp w9, #253
+; CHECK-NEXT: cmn w9, #3
; CHECK-NEXT: mov w9, #8
; CHECK-NEXT: csel w0, w9, w8, lo
; CHECK-NEXT: ret
diff --git a/llvm/test/Transforms/TypePromotion/ARM/casts.ll b/llvm/test/Transforms/TypePromotion/ARM/casts.ll
index 7cd9cba0b7097..d733e00357ec7 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/casts.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/casts.ll
@@ -138,8 +138,8 @@ define i1 @or_icmp_ugt(i32 %arg, i8* %ptr) {
; CHECK-NEXT: [[MUL:%.*]] = shl nuw nsw i32 [[TMP2]], 1
; CHECK-NEXT: [[ADD0:%.*]] = add nuw nsw i32 [[MUL]], 6
; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 [[ARG:%.*]], [[ADD0]]
-; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP1]], 1
-; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[TMP3]], 3
+; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP1]], -1
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[ADD1]], 3
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP0]], [[CMP1]]
; CHECK-NEXT: ret i1 [[OR]]
;
diff --git a/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll b/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
index 117c4c0d5c8a4..1735e736447d1 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
@@ -39,9 +39,9 @@ define i32 @clear_structures(i8* nocapture readonly %fmt, [1 x i32] %ap.coerce,
; CHECK-NEXT: [[INCDEC_PTR23:%.*]] = getelementptr inbounds i8, i8* [[FMT_ADDR_0_PN]], i32 2
; CHECK-NEXT: [[DOTPR74:%.*]] = load i8, i8* [[INCDEC_PTR23]], align 1
; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[DOTPR74]] to i32
-; CHECK-NEXT: [[TMP4:%.*]] = sub i32 [[TMP3]], 48
-; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 10
-; CHECK-NEXT: br i1 [[TMP5]], label [[WHILE_COND24:%.*]], label [[COND_END]]
+; CHECK-NEXT: [[DOTPR74_OFF:%.*]] = add i32 [[TMP3]], -48
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[DOTPR74_OFF]], 10
+; CHECK-NEXT: br i1 [[TMP4]], label [[WHILE_COND24:%.*]], label [[COND_END]]
; CHECK: while.cond24:
; CHECK-NEXT: br label [[WHILE_COND24]]
; CHECK: cond.end:
diff --git a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll
index f5cf2bc43681c..7aa1e7dbc4e5c 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll
@@ -65,8 +65,8 @@ define i32 @test_ugt_1_dec_imm(i8 zeroext %x) {
; CHECK-LABEL: @test_ugt_1_dec_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -193,8 +193,8 @@ define i32 @ugt_1_dec_imm(i8 zeroext %x) {
; CHECK-LABEL: @ugt_1_dec_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -305,8 +305,9 @@ define i32 @icmp_minus_imm(i8* %a) {
; CHECK-LABEL: @icmp_minus_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[A:%.*]], align 1
-; CHECK-NEXT: [[ADD_I:%.*]] = add i8 [[TMP0]], -7
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD_I]], -5
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[TMP1]], -7
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD_I]], -5
; CHECK-NEXT: [[CONV1:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV1]]
;
diff --git a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
index 23e50dec0ca10..1e5e3937c7f5d 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
@@ -102,8 +102,9 @@ define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
define i32 @unsafe_add_underflow(i8 zeroext %a) {
; CHECK-LABEL: @unsafe_add_underflow(
-; CHECK-NEXT: [[ADD:%.*]] = add i8 [[A:%.*]], -2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD]], -2
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], -2
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -116,8 +117,8 @@ define i32 @unsafe_add_underflow(i8 zeroext %a) {
define i32 @safe_add_underflow(i8 zeroext %a) {
; CHECK-LABEL: @safe_add_underflow(
; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[TMP2]], 254
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], -1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], 254
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -130,8 +131,8 @@ define i32 @safe_add_underflow(i8 zeroext %a) {
define i32 @safe_add_underflow_neg(i8 zeroext %a) {
; CHECK-LABEL: @safe_add_underflow_neg(
; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[TMP2]], 250
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], -2
+; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[ADD]], 250
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -154,10 +155,12 @@ define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
ret i32 %res
}
-define i32 @unsafe_sub_underflow(i8 zeroext %a) {
-; CHECK-LABEL: @unsafe_sub_underflow(
-; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A:%.*]], 6
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SUB]], -6
+; This is valid so long as the icmp immediate is sext.
+define i32 @sext_sub_underflow(i8 zeroext %a) {
+; CHECK-LABEL: @sext_sub_underflow(
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[TMP1]], 6
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[SUB]], -6
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -195,10 +198,12 @@ define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
ret i32 %res
}
-define i32 @unsafe_sub_underflow_neg(i8 zeroext %a) {
-; CHECK-LABEL: @unsafe_sub_underflow_neg(
-; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A:%.*]], 4
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[SUB]], -3
+; This is valid so long as the icmp immediate is sext.
+define i32 @sext_sub_underflow_neg(i8 zeroext %a) {
+; CHECK-LABEL: @sext_sub_underflow_neg(
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[TMP1]], 4
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], -3
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
; CHECK-NEXT: ret i32 [[RES]]
;
@@ -288,12 +293,12 @@ define i8 @convert_add_order(i8 zeroext %arg) {
; CHECK-NEXT: [[SHL:%.*]] = or i32 [[TMP1]], 1
; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[SHL]], 10
; CHECK-NEXT: [[CMP_0:%.*]] = icmp ult i32 [[ADD]], 60
-; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 [[SHL]], 40
-; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[TMP2]], 20
+; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[SHL]], -40
+; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[SUB]], 20
; CHECK-NEXT: [[MASK_SEL:%.*]] = select i1 [[CMP_1]], i32 [[MASK_0]], i32 [[MASK_1]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_0]], i32 [[MASK_SEL]], i32 [[TMP1]]
-; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[RES]] to i8
-; CHECK-NEXT: ret i8 [[TMP3]]
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[RES]] to i8
+; CHECK-NEXT: ret i8 [[TMP2]]
;
%mask.0 = and i8 %arg, 1
%mask.1 = and i8 %arg, 2
More information about the llvm-commits
mailing list