diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp --- a/llvm/lib/CodeGen/TypePromotion.cpp +++ b/llvm/lib/CodeGen/TypePromotion.cpp @@ -486,7 +486,10 @@ if (auto *Const = dyn_cast(Op)) { // For subtract, we don't need to sext the constant. We only put it in // SafeWrap because SafeWrap.size() is used elsewhere. - Constant *NewConst = (SafeWrap.contains(I) && i == 1 && + // For cmp, we need to sign extend a constant appearing in either + // operand. For add, we should only sign extend the RHS. + Constant *NewConst = (SafeWrap.contains(I) && + (I->getOpcode() == Instruction::ICmp || i == 1) && I->getOpcode() != Instruction::Sub) ? ConstantExpr::getSExt(Const, ExtTy) : ConstantExpr::getZExt(Const, ExtTy); diff --git a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll --- a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll +++ b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll @@ -319,6 +319,24 @@ ret i32 %conv1 } +define i32 @icmp_minus_imm_noncanonicalcmp(i8* %a) { +; CHECK-LABEL: @icmp_minus_imm_noncanonicalcmp( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[A:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[TMP1]], -7 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 -5, [[ADD_I]] +; CHECK-NEXT: [[CONV1:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: ret i32 [[CONV1]] +; +entry: + %0 = load i8, i8* %a, align 1 + %add.i = add i8 %0, -7 + %cmp = icmp ult i8 -5, %add.i + %conv1 = zext i1 %cmp to i32 + ret i32 %conv1 +} + define void @mul_with_neg_imm(i32, i32* %b) { ; CHECK-LABEL: @mul_with_neg_imm( ; CHECK-NEXT: entry: