Index: llvm/lib/CodeGen/TypePromotion.cpp =================================================================== --- llvm/lib/CodeGen/TypePromotion.cpp +++ llvm/lib/CodeGen/TypePromotion.cpp @@ -733,8 +733,8 @@ } } else if (isa(V) && !isa(V)) { return isSupportedType(V); - } else if (isa(V)) - return isSupportedType(V); + } else if (auto Arg = dyn_cast(V)) + return !Arg->hasSExtAttr() && isSupportedType(V); return isa(V); } @@ -858,7 +858,7 @@ if (Sources.count(V)) { if (auto *Arg = dyn_cast(V)) - if (!Arg->hasZExtAttr() && !Arg->hasSExtAttr()) + if (!Arg->hasZExtAttr()) ++NonFreeArgs; continue; } Index: llvm/test/CodeGen/AArch64/typepromotion-overflow.ll =================================================================== --- llvm/test/CodeGen/AArch64/typepromotion-overflow.ll +++ llvm/test/CodeGen/AArch64/typepromotion-overflow.ll @@ -328,8 +328,8 @@ ; CHECK-NEXT: mov w9, #100 ; CHECK-NEXT: cset w8, gt ; CHECK-NEXT: and w8, w8, w0 -; CHECK-NEXT: add w8, w8, #245 -; CHECK-NEXT: cmp w8, w1, uxtb +; CHECK-NEXT: sub w8, w8, #11 +; CHECK-NEXT: cmp w8, w1 ; CHECK-NEXT: csel w0, w8, w9, lo ; CHECK-NEXT: ret %cmp = icmp sgt i32 %arg, 0 Index: llvm/test/CodeGen/AArch64/typepromotion-phisret.ll =================================================================== --- llvm/test/CodeGen/AArch64/typepromotion-phisret.ll +++ llvm/test/CodeGen/AArch64/typepromotion-phisret.ll @@ -234,25 +234,27 @@ define i16 @signext_bitcast_phi_select(i16 signext %start, i16* %in) { ; CHECK-LABEL: signext_bitcast_phi_select: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: and w8, w0, #0xffff ; CHECK-NEXT: mov w9, #-1 -; CHECK-NEXT: cmp w9, w8, sxth +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: cmp w9, w0, sxth ; CHECK-NEXT: b.lt .LBB6_3 ; CHECK-NEXT: .LBB6_1: // %if.then ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: ldrh w0, [x1, w8, sxtw #1] -; CHECK-NEXT: cmp w0, w8 +; CHECK-NEXT: sxth x8, w0 +; CHECK-NEXT: ldrh w8, [x1, x8, lsl #1] +; CHECK-NEXT: cmp w8, w0, uxth ; CHECK-NEXT: b.eq .LBB6_4 ; CHECK-NEXT: // %bb.2: // %if.else ; CHECK-NEXT: // in Loop: Header=BB6_1 Depth=1 -; CHECK-NEXT: lsr w10, w8, #15 -; CHECK-NEXT: eor w10, w10, #0x1 -; CHECK-NEXT: add w8, w10, w8 -; CHECK-NEXT: cmp w9, w8, sxth +; CHECK-NEXT: mvn w8, w0 +; CHECK-NEXT: and w8, w8, #0x8000 +; CHECK-NEXT: add w0, w0, w8, lsr #15 +; CHECK-NEXT: cmp w9, w0, sxth ; CHECK-NEXT: b.ge .LBB6_1 ; CHECK-NEXT: .LBB6_3: -; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: mov w8, wzr ; CHECK-NEXT: .LBB6_4: // %exit +; CHECK-NEXT: mov w0, w8 ; CHECK-NEXT: ret entry: %const = bitcast i16 -1 to i16 Index: llvm/test/CodeGen/AArch64/typepromotion-signed.ll =================================================================== --- llvm/test/CodeGen/AArch64/typepromotion-signed.ll +++ llvm/test/CodeGen/AArch64/typepromotion-signed.ll @@ -76,7 +76,8 @@ ; CHECK-LABEL: test_signext_b_ult_slt: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ldrb w8, [x0] -; CHECK-NEXT: add w9, w8, w1, uxtb +; CHECK-NEXT: add w9, w8, w1 +; CHECK-NEXT: and w9, w9, #0xff ; CHECK-NEXT: cmp w9, #127 ; CHECK-NEXT: mov w9, #42 ; CHECK-NEXT: ccmp w8, #0, #0, ne Index: llvm/test/Transforms/TypePromotion/ARM/casts.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/casts.ll +++ llvm/test/Transforms/TypePromotion/ARM/casts.ll @@ -52,8 +52,8 @@ ; The pass perform the transform, but a uxtb will still be inserted to handle ; the zext to the icmp. -define i8 @icmp_i32_zext(i8* %ptr) { -; CHECK-LABEL: @icmp_i32_zext( +define i8 @icmp_i32_zext_i8(i8* %ptr) { +; CHECK-LABEL: @icmp_i32_zext_i8( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i32 0 ; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[GEP]], align 1 @@ -103,6 +103,112 @@ ret i8 %2 } +define i32 @icmp_i16_zext_i8(i8* %ptr) { +; CHECK-LABEL: @icmp_i16_zext_i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i32 0 +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[GEP]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i8 [[TMP0]], 1 +; CHECK-NEXT: [[CONV44:%.*]] = zext i8 [[TMP0]] to i16 +; CHECK-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[BODY:%.*]] +; CHECK: body: +; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ [[TMP1]], [[PREHEADER]] ], [ [[TMP3:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[SI_0274:%.*]] = phi i16 [ [[CONV44]], [[PREHEADER]] ], [ [[INC:%.*]], [[IF_END]] ] +; CHECK-NEXT: [[CONV51266:%.*]] = zext i8 [[TMP2]] to i16 +; CHECK-NEXT: [[CMP52267:%.*]] = icmp eq i16 [[SI_0274]], [[CONV51266]] +; CHECK-NEXT: br i1 [[CMP52267]], label [[IF_END]], label [[EXIT:%.*]] +; CHECK: if.end: +; CHECK-NEXT: [[INC]] = add i16 [[SI_0274]], 1 +; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[INC]] +; CHECK-NEXT: [[TMP3]] = load i8, i8* [[GEP1]], align 1 +; CHECK-NEXT: br label [[BODY]] +; CHECK: exit: +; CHECK-NEXT: [[RET:%.*]] = zext i16 [[CONV51266]] to i32 +; CHECK-NEXT: ret i32 [[RET]] +; +entry: + %gep = getelementptr inbounds i8, i8* %ptr, i32 0 + %0 = load i8, i8* %gep, align 1 + %1 = sub nuw nsw i8 %0, 1 + %conv44 = zext i8 %0 to i16 + br label %preheader + +preheader: + br label %body + +body: + %2 = phi i8 [ %1, %preheader ], [ %3, %if.end ] + %si.0274 = phi i16 [ %conv44, %preheader ], [ %inc, %if.end ] + %conv51266 = zext i8 %2 to i16 + %cmp52267 = icmp eq i16 %si.0274, %conv51266 + br i1 %cmp52267, label %if.end, label %exit + +if.end: + %inc = add i16 %si.0274, 1 + %gep1 = getelementptr inbounds i8, i8* %ptr, i16 %inc + %3 = load i8, i8* %gep1, align 1 + br label %body + +exit: + %ret = zext i16 %conv51266 to i32 + ret i32 %ret +} + +define i32 @icmp_i32_zext_i16(i16* %ptr) { +; CHECK-LABEL: @icmp_i32_zext_i16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i16, i16* [[PTR:%.*]], i32 0 +; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[GEP]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i16 [[TMP0]], 1 +; CHECK-NEXT: [[CONV44:%.*]] = zext i16 [[TMP0]] to i32 +; CHECK-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[BODY:%.*]] +; CHECK: body: +; CHECK-NEXT: [[TMP2:%.*]] = phi i16 [ [[TMP1]], [[PREHEADER]] ], [ [[TMP3:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[SI_0274:%.*]] = phi i32 [ [[CONV44]], [[PREHEADER]] ], [ [[INC:%.*]], [[IF_END]] ] +; CHECK-NEXT: [[CONV51266:%.*]] = zext i16 [[TMP2]] to i32 +; CHECK-NEXT: [[CMP52267:%.*]] = icmp eq i32 [[SI_0274]], [[CONV51266]] +; CHECK-NEXT: br i1 [[CMP52267]], label [[IF_END]], label [[EXIT:%.*]] +; CHECK: if.end: +; CHECK-NEXT: [[INC]] = add i32 [[SI_0274]], 1 +; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i16, i16* [[PTR]], i32 [[INC]] +; CHECK-NEXT: [[TMP3]] = load i16, i16* [[GEP1]], align 1 +; CHECK-NEXT: br label [[BODY]] +; CHECK: exit: +; CHECK-NEXT: [[RET:%.*]] = sext i16 [[TMP2]] to i32 +; CHECK-NEXT: ret i32 [[RET]] +; +entry: + %gep = getelementptr inbounds i16, i16* %ptr, i32 0 + %0 = load i16, i16* %gep, align 1 + %1 = sub nuw nsw i16 %0, 1 + %conv44 = zext i16 %0 to i32 + br label %preheader + +preheader: + br label %body + +body: + %2 = phi i16 [ %1, %preheader ], [ %3, %if.end ] + %si.0274 = phi i32 [ %conv44, %preheader ], [ %inc, %if.end ] + %conv51266 = zext i16 %2 to i32 + %cmp52267 = icmp eq i32 %si.0274, %conv51266 + br i1 %cmp52267, label %if.end, label %exit + +if.end: + %inc = add i32 %si.0274, 1 + %gep1 = getelementptr inbounds i16, i16* %ptr, i32 %inc + %3 = load i16, i16* %gep1, align 1 + br label %body + +exit: + %ret = sext i16 %2 to i32 + ret i32 %ret +} + ; Won't don't handle sext define i32 @icmp_sext_zext_store_i8_i16() { ; CHECK-LABEL: @icmp_sext_zext_store_i8_i16( Index: llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll +++ llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll @@ -27,7 +27,7 @@ ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ] -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[INC2]], 255 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[INC2]], 25 ; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -58,7 +58,7 @@ if.end: %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ] - %cmp1 = icmp eq i8 %inc2, 255 + %cmp1 = icmp eq i8 %inc2, 25 br i1 %cmp1, label %exit, label %loop exit: @@ -90,7 +90,7 @@ ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ] -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[INC2]], 255 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[INC2]], 55 ; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -121,7 +121,7 @@ if.end: %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ] - %cmp1 = icmp eq i8 %inc2, 255 + %cmp1 = icmp eq i8 %inc2, 55 br i1 %cmp1, label %exit, label %loop exit: @@ -293,29 +293,25 @@ define i16 @signext_bitcast_phi_select(i16 signext %start, i16* %in) { ; CHECK-LABEL: @signext_bitcast_phi_select( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[START:%.*]] to i32 ; CHECK-NEXT: [[CONST:%.*]] = bitcast i16 -1 to i16 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[SELECT:%.*]], [[IF_ELSE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[IDX]] to i16 -; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i16 [[TMP1]], [[CONST]] +; CHECK-NEXT: [[IDX:%.*]] = phi i16 [ [[SELECT:%.*]], [[IF_ELSE:%.*]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i16 [[IDX]], [[CONST]] ; CHECK-NEXT: br i1 [[CMP_I]], label [[EXIT:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[IDX_NEXT:%.*]] = getelementptr i16, i16* [[IN:%.*]], i32 [[IDX]] +; CHECK-NEXT: [[IDX_NEXT:%.*]] = getelementptr i16, i16* [[IN:%.*]], i16 [[IDX]] ; CHECK-NEXT: [[LD:%.*]] = load i16, i16* [[IDX_NEXT]], align 2 -; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[LD]] to i32 -; CHECK-NEXT: [[CMP1_I:%.*]] = icmp eq i32 [[TMP2]], [[IDX]] +; CHECK-NEXT: [[CMP1_I:%.*]] = icmp eq i16 [[LD]], [[IDX]] ; CHECK-NEXT: br i1 [[CMP1_I]], label [[EXIT]], label [[IF_ELSE]] ; CHECK: if.else: -; CHECK-NEXT: [[LOBIT:%.*]] = lshr i32 [[IDX]], 15 -; CHECK-NEXT: [[LOBIT_NOT:%.*]] = xor i32 [[LOBIT]], 1 -; CHECK-NEXT: [[SELECT]] = add nuw i32 [[LOBIT_NOT]], [[IDX]] +; CHECK-NEXT: [[LOBIT:%.*]] = lshr i16 [[IDX]], 15 +; CHECK-NEXT: [[LOBIT_NOT:%.*]] = xor i16 [[LOBIT]], 1 +; CHECK-NEXT: [[SELECT]] = add nuw i16 [[LOBIT_NOT]], [[IDX]] ; CHECK-NEXT: br label [[FOR_BODY]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[RES]] to i16 -; CHECK-NEXT: ret i16 [[TMP3]] +; CHECK-NEXT: [[RES:%.*]] = phi i16 [ [[LD]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECK-NEXT: ret i16 [[RES]] ; entry: %const = bitcast i16 -1 to i16 Index: llvm/test/Transforms/TypePromotion/ARM/signed.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/signed.ll +++ llvm/test/Transforms/TypePromotion/ARM/signed.ll @@ -62,11 +62,9 @@ define i32 @test_signext_b(i8* %ptr, i8 signext %arg) { ; CHECK-LABEL: @test_signext_b( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32 -; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP3]], 128 +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[PTR:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP1]], -128 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 42, i32 20894 ; CHECK-NEXT: ret i32 [[RES]] ; @@ -81,13 +79,10 @@ define i32 @test_signext_b_ult_slt(i8* %ptr, i8 signext %arg) { ; CHECK-LABEL: @test_signext_b_ult_slt( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32 -; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i8 -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[TMP4]], 126 -; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i32 [[TMP3]], [[TMP0]] +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[PTR:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[TMP1]], 126 +; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[TMP1]], [[ARG]] ; CHECK-NEXT: [[OR:%.*]] = and i1 [[CMP]], [[CMP_1]] ; CHECK-NEXT: [[RES:%.*]] = select i1 [[OR]], i32 42, i32 57 ; CHECK-NEXT: ret i32 [[RES]] @@ -105,11 +100,9 @@ define i32 @test_signext_h(i16* %ptr, i16 signext %arg) { ; CHECK-LABEL: @test_signext_h( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[ARG:%.*]] to i32 -; CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP3]], 32768 +; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[PTR:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i16 [[TMP0]], [[ARG:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[TMP1]], -32768 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 42, i32 20894 ; CHECK-NEXT: ret i32 [[RES]] ; Index: llvm/test/Transforms/TypePromotion/ARM/wrapping.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/wrapping.ll +++ llvm/test/Transforms/TypePromotion/ARM/wrapping.ll @@ -338,17 +338,14 @@ define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) { ; CHECK-LABEL: @underflow_if_sub_signext( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ARG:%.*]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARG]], [[CONV]] ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[AND]] to i8 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TRUNC]] to i32 -; CHECK-NEXT: [[CONV1:%.*]] = add nuw nsw i32 [[TMP2]], 245 -; CHECK-NEXT: [[CMP_1:%.*]] = icmp ugt i32 [[TMP1]], [[CONV1]] -; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_1]], i32 [[CONV1]], i32 100 -; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[RES]] to i8 -; CHECK-NEXT: ret i8 [[TMP3]] +; CHECK-NEXT: [[CONV1:%.*]] = add nuw nsw i8 [[TRUNC]], -11 +; CHECK-NEXT: [[CMP_1:%.*]] = icmp ugt i8 [[ARG1:%.*]], [[CONV1]] +; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_1]], i8 [[CONV1]], i8 100 +; CHECK-NEXT: ret i8 [[RES]] ; %cmp = icmp sgt i32 %arg, 0 %conv = zext i1 %cmp to i32