Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2899,14 +2899,115 @@ BinaryOperator *Add, const APInt &C) { Value *Y = Add->getOperand(1); + Value *X = Add->getOperand(0); + + Value *Op0 = X, *Op1 = Y; + const CmpInst::Predicate Pred = Cmp.getPredicate(); + + // We handle all (s/zext i1 Op0 + s/zext i1 Op1 ==/!= 0/1/2) here. + // TODO: sext -1, sext -2 + // sext i1 X + sext i1 Y == -1 --> xor i1 X, Y + // https://alive2.llvm.org/ce/z/2nSJ22 + // sext i1 X + sext i1 Y == -2 --> and i1 X, Y + // https://alive2.llvm.org/ce/z/rasQlX + if (Cmp.isEquality() && + match(Add, m_c_Add(m_OneUse(m_ZExtOrSExt(m_Value(Op0))), + m_OneUse(m_ZExtOrSExt(m_Value(Op1))))) && + Op0->getType()->isIntOrIntVectorTy(1) && + Op1->getType()->isIntOrIntVectorTy(1) && + (C.isZero() || C.isOne() || (C.exactLogBase2() == 1))) { + Value *Cond = Builder.getFalse(); + // Handle zext/zext additions + if (match(X, m_OneUse(m_ZExt(m_Value(Op0)))) && + match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) { + if (Pred == ICmpInst::ICMP_EQ) { + // Case 1: zext i1 Op0 + zext i1 Op1 == 0 --> !(or i1 Op0, Op1) + if (C.isZero()) + Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1)); + else if (C.isOne()) + // Case 2: zext i1 Op0 + zext i1 Op1 == 1 --> xor i1 Op0, Op1 + Cond = Builder.CreateXor(Op0, Op1); + else + // Case 3: zext i1 Op0 + zext i1 Op1 == 2 --> xor i1 Op0, Op1 + Cond = Builder.CreateAnd(Op0, Op1); + } else { + // Case 1: zext i1 Op0 + zext i1 Op1 != 0 --> or i1 Op0, Op1 + if (C.isZero()) + Cond = Builder.CreateOr(Op0, Op1); + else if (C.isOne()) + // Case 2: zext i1 Op0 + zext i1 Op1 != 1 --> !(xor i1 Op0, Op1) + Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1)); + else + // Case 3: zext i1 Op0 + zext i1 Op1 != 2 --> !(and i1 Op0, Op1) + Cond = Builder.CreateNot(Builder.CreateAnd(Op0, Op1)); + } + return replaceInstUsesWith(Cmp, Cond); + } + + // Handles sext i1 Op0 + sext i1 Op1 ==/!= 0/1/2 + if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) && + match(Y, m_OneUse(m_SExt(m_Value(Op1))))) { + if (Pred == ICmpInst::ICMP_EQ) { + // Case 1: sext i1 Op0 + sext i1 Op1 == 0 --> !(or i1 Op0, Op1) + if (C.isZero()) + Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1)); + // Case 2: sext i1 Op0 + sext i1 Op1 == 1 --> false + // Case 3: sext i1 Op0 + sext i1 Op2 == 2 --> false, + else + Cond = Builder.getFalse(); + } else { + // Case 1: sext i1 Op0 + sext i1 Op1 != 0 --> or i1 Op0, Op1 + if (C.isZero()) + Cond = Builder.CreateOr(Op0, Op1); + else + // Case 2: sext i1 Op0 + sext i1 Op1 != 1 --> true + // Case 3: sext i1 Op0 + sext i1 Op2 != 2 --> true + Cond = Builder.getTrue(); + } + return replaceInstUsesWith(Cmp, Cond); + } + + // Sum is cummulative so swap the operations to avoid recompuations + if (match(X, m_OneUse(m_ZExt(m_OneUse(m_Value(Op0))))) && + match(Y, m_OneUse(m_SExt(m_OneUse(m_Value(Op1)))))) { + std::swap(Op0, Op1); + std::swap(X, Y); + } + // Handles sext i1 Op0 + zext Op1 == 0/1/2 + if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) && + match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) { + if (Pred == ICmpInst::ICMP_EQ) { + // Case 1: sext i1 Op0 + zext i1 Op1 == 0 --> !(xor i1 Op0, Op1) + if (C.isZero()) + Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1)); + else if (C.isOne()) + // Case 2: sext i1 Op0 + zext i1 Op1 == 1 --> (!Op0) & Op1 + Cond = Builder.CreateAnd(Builder.CreateNot(Op0), Op1); + else + // Case 3: sext i1 Op0 + zext i1 Op1 == 2 --> false + Cond = Builder.getFalse(); + } else { + // Case 1: sext i1 Op0 + zext i1 Op1 != 0 --> xor i1 Op0, Op1 + if (C.isZero()) + Cond = Builder.CreateXor(Op0, Op1); + else if (C.isOne()) + // Case 2: sext i1 Op0 + zext i1 Op1 != 1 --> Op0 | (!Op1) + Cond = Builder.CreateOr(Op0, Builder.CreateNot(Op1)); + else + // Case 3: sext i1 Op0 + zext i1 Op1 != 2 --> true + Cond = Builder.getTrue(); + } + return replaceInstUsesWith(Cmp, Cond); + } + return nullptr; + } + const APInt *C2; if (Cmp.isEquality() || !match(Y, m_APInt(C2))) return nullptr; // Fold icmp pred (add X, C2), C. - Value *X = Add->getOperand(0); Type *Ty = Add->getType(); - const CmpInst::Predicate Pred = Cmp.getPredicate(); // If the add does not wrap, we can always adjust the compare by subtracting // the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE Index: llvm/test/Transforms/InstCombine/icmp-add.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-add.ll +++ llvm/test/Transforms/InstCombine/icmp-add.ll @@ -5,6 +5,756 @@ ; PR1949 +define i1 @cvt_icmp_0_zext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp eq i32 %i3, 0 + ret i1 %i4 +} + +define i1 @cvt_icmp_1_zext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp eq i32 %i3, 1 + ret i1 %i4 +} + +define i1 @cvt_icmp_2_zext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[T:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_sext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: [[T:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_sext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_sext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_sext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: [[T:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_sext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_sext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true +; CHECK-NEXT: [[T:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_sext_plus_zext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_zext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ne i32 %i3, 0 + ret i1 %i4 +} + +define i1 @cvt_icmp_1_zext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ne i32 %i3, 1 + ret i1 %i4 +} + +define i1 @cvt_icmp_2_zext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: [[T:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_sext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[T:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_sext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 true +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_sext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 true +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_sext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[T:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_sext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_sext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true +; CHECK-NEXT: [[T:%.*]] = or i1 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_sext_plus_zext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 true +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 2 + ret i1 %t +} + +; test if zext i1 X + sext i1 Y converted to sext i1 X + zext i1 Y +; and then processed + +define i1 @cvt_icmp_0_zext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[T:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_zext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_zext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true +; CHECK-NEXT: [[T:%.*]] = and i1 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_zext_plus_sext_eq(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_eq( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp eq i32 %i3, 2 + ret i1 %t +} + +define i1 @cvt_icmp_0_zext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[T:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 0 + ret i1 %t +} + +define i1 @cvt_icmp_1_zext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_1_zext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true +; CHECK-NEXT: [[T:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 1 + ret i1 %t +} + +define i1 @cvt_icmp_2_zext_plus_sext_ne(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_ne( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 true +; +bb: + %i = zext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i, %i2 + %t = icmp ne i32 %i3, 2 + ret i1 %t +} + +; test zext/zext additions with more than one use + +define i1 @test_cvt_icmp1(i1 %arg, i1 %arg1, ptr %p) { +; CHECK-LABEL: @test_cvt_icmp1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = zext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG]] to i32 +; CHECK-NEXT: store i32 [[I2]], ptr [[P:%.*]], align 4 +; CHECK-NEXT: [[I4:%.*]] = add nuw nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[T:%.*]] = icmp eq i32 [[I4]], 1 +; CHECK-NEXT: ret i1 [[T]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg to i32 + store i32 %i2, ptr %p + %i3 = load i32, ptr %p + %i4 = add i32 %i3, %i + %t = icmp eq i32 %i4, 1 + ret i1 %t +} + +define i1 @test_cvt_icmp2(i1 %arg, i1 %arg1, ptr %p) { +; CHECK-LABEL: @test_cvt_icmp2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: store i32 [[I2]], ptr [[P:%.*]], align 4 +; CHECK-NEXT: ret i1 false +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg to i32 + store i32 %i2, ptr %p + %i3 = load i32, ptr %p + %i4 = add i32 %i3, %i + %t = icmp eq i32 %i4, 1 + ret i1 %t +} + +; tests for negative comparisons +define i1 @test_cvt_icmp3(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp3( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ult i32 %i3, 0 + ret i1 %i4 +} + +define i1 @test_cvt_icmp4(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp4( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ugt i32 %i3, 0 + ret i1 %i4 +} + +define i1 @test_cvt_icmp5(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp5( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp uge i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp6(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp6( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = zext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ult i32 [[I3]], 2 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ule i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp7(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp7( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = zext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ugt i32 [[I3]], 1 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sgt i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp8(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp8( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sge i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp9(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp9( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp slt i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp10(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp10( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = zext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ult i32 [[I3]], 2 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = zext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sle i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp11(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp11( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ugt i32 [[I3]], 2 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ugt i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp12(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp12( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp uge i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp13(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp13( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[TMP0]], true +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ult i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp14(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp14( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ult i32 [[I3]], 3 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ule i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp15(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp15( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp sgt i32 [[I3]], 2 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sgt i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp16(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp16( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp sgt i32 [[I3]], 1 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sge i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp17(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp17( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp slt i32 [[I3]], 2 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp slt i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp18(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp18( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp slt i32 [[I3]], 3 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = sext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sle i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp19(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp19( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true +; CHECK-NEXT: [[I4:%.*]] = and i1 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ugt i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp20(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp20( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I4:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp uge i32 %i3, 1 + ret i1 %i4 +} + +define i1 @test_cvt_icmp21(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp21( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[ARG_NOT:%.*]] = xor i1 [[ARG:%.*]], true +; CHECK-NEXT: [[I4:%.*]] = or i1 [[ARG_NOT]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ult i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp22(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp22( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = sext i1 [[ARG:%.*]] to i32 +; CHECK-NEXT: [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32 +; CHECK-NEXT: [[I3:%.*]] = add nsw i32 [[I2]], [[I]] +; CHECK-NEXT: [[I4:%.*]] = icmp ult i32 [[I3]], 3 +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp ule i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp23(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp23( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 false +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sgt i32 %i3, 2 + ret i1 %i4 +} + +define i1 @test_cvt_icmp24(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp24( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true +; CHECK-NEXT: [[I4:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sge i32 %i3, 0 + ret i1 %i4 +} + +define i1 @test_cvt_icmp25(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp25( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true +; CHECK-NEXT: [[I4:%.*]] = and i1 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: ret i1 [[I4]] +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp slt i32 %i3, 0 + ret i1 %i4 +} + +define i1 @test_cvt_icmp26(i1 %arg, i1 %arg1) { +; CHECK-LABEL: @test_cvt_icmp26( +; CHECK-NEXT: bb: +; CHECK-NEXT: ret i1 true +; +bb: + %i = sext i1 %arg to i32 + %i2 = zext i1 %arg1 to i32 + %i3 = add i32 %i2, %i + %i4 = icmp sle i32 %i3, 1 + ret i1 %i4 +} + define i1 @test1(i32 %a) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A:%.*]], -5