; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+f,+zknh,+v -target-abi=lp64f \ ; RUN: | FileCheck %s --check-prefixes=CHECK,RV64I ; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zba,+zbb,+f,+zknh,+v -target-abi=lp64f \ ; RUN: | FileCheck %s --check-prefixes=CHECK,RV64ZBB ; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zba,+zbb,+f,+zknh,+v -target-abi=lp64f \ ; RUN: -riscv-disable-sextw-removal | FileCheck %s --check-prefix=NOREMOVAL define void @test1(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test1: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: mv s0, a1 ; CHECK-NEXT: sraw s1, a0, a1 ; CHECK-NEXT: .LBB0_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: mv a0, s1 ; CHECK-NEXT: call bar ; CHECK-NEXT: sllw s1, s1, s0 ; CHECK-NEXT: bnez a0, .LBB0_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test1: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -32 ; NOREMOVAL-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: mv s0, a1 ; NOREMOVAL-NEXT: sraw s1, a0, a1 ; NOREMOVAL-NEXT: .LBB0_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, s1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: sllw s1, s1, s0 ; NOREMOVAL-NEXT: bnez a0, .LBB0_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 32 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = shl i32 %i3, %arg1 %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare signext i32 @bar(i32 signext) ; The load here was previously an aext load, but this has since been changed ; to a signext load allowing us to remove a sext.w before isel. Thus we get ; the same result with or without the sext.w removal pass. ; Test has been left for coverage purposes. define signext i32 @test2(ptr %p, i32 signext %b) nounwind { ; RV64I-LABEL: test2: ; RV64I: # %bb.0: ; RV64I-NEXT: lw a0, 0(a0) ; RV64I-NEXT: li a2, 1 ; RV64I-NEXT: sllw a1, a2, a1 ; RV64I-NEXT: not a1, a1 ; RV64I-NEXT: and a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: test2: ; RV64ZBB: # %bb.0: ; RV64ZBB-NEXT: lw a0, 0(a0) ; RV64ZBB-NEXT: li a2, -2 ; RV64ZBB-NEXT: rolw a1, a2, a1 ; RV64ZBB-NEXT: and a0, a1, a0 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: test2: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: lw a0, 0(a0) ; NOREMOVAL-NEXT: li a2, -2 ; NOREMOVAL-NEXT: rolw a1, a2, a1 ; NOREMOVAL-NEXT: and a0, a1, a0 ; NOREMOVAL-NEXT: ret %a = load i32, ptr %p %shl = shl i32 1, %b %neg = xor i32 %shl, -1 %and1 = and i32 %neg, %a ret i32 %and1 } define signext i32 @test3(ptr %p, i32 signext %b) nounwind { ; RV64I-LABEL: test3: ; RV64I: # %bb.0: ; RV64I-NEXT: lw a0, 0(a0) ; RV64I-NEXT: li a2, 1 ; RV64I-NEXT: sllw a1, a2, a1 ; RV64I-NEXT: not a1, a1 ; RV64I-NEXT: or a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: test3: ; RV64ZBB: # %bb.0: ; RV64ZBB-NEXT: lw a0, 0(a0) ; RV64ZBB-NEXT: li a2, -2 ; RV64ZBB-NEXT: rolw a1, a2, a1 ; RV64ZBB-NEXT: or a0, a1, a0 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: test3: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: lw a0, 0(a0) ; NOREMOVAL-NEXT: li a2, -2 ; NOREMOVAL-NEXT: rolw a1, a2, a1 ; NOREMOVAL-NEXT: or a0, a1, a0 ; NOREMOVAL-NEXT: ret %a = load i32, ptr %p %shl = shl i32 1, %b %neg = xor i32 %shl, -1 %and1 = or i32 %neg, %a ret i32 %and1 } define signext i32 @test4(ptr %p, i32 signext %b) nounwind { ; RV64I-LABEL: test4: ; RV64I: # %bb.0: ; RV64I-NEXT: lw a0, 0(a0) ; RV64I-NEXT: li a2, 1 ; RV64I-NEXT: sllw a1, a2, a1 ; RV64I-NEXT: xor a0, a1, a0 ; RV64I-NEXT: not a0, a0 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: test4: ; RV64ZBB: # %bb.0: ; RV64ZBB-NEXT: lw a0, 0(a0) ; RV64ZBB-NEXT: li a2, 1 ; RV64ZBB-NEXT: sllw a1, a2, a1 ; RV64ZBB-NEXT: xnor a0, a1, a0 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: test4: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: lw a0, 0(a0) ; NOREMOVAL-NEXT: li a2, 1 ; NOREMOVAL-NEXT: sllw a1, a2, a1 ; NOREMOVAL-NEXT: xnor a0, a1, a0 ; NOREMOVAL-NEXT: ret %a = load i32, ptr %p %shl = shl i32 1, %b %neg = xor i32 %shl, -1 %and1 = xor i32 %neg, %a ret i32 %and1 } ; Make sure we don't put a sext.w before bar when using cpopw. define void @test5(i32 signext %arg, i32 signext %arg1) nounwind { ; RV64I-LABEL: test5: ; RV64I: # %bb.0: # %bb ; RV64I-NEXT: addi sp, sp, -48 ; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: sraw a0, a0, a1 ; RV64I-NEXT: lui a1, 349525 ; RV64I-NEXT: addiw s0, a1, 1365 ; RV64I-NEXT: lui a1, 209715 ; RV64I-NEXT: addiw s1, a1, 819 ; RV64I-NEXT: lui a1, 61681 ; RV64I-NEXT: addi s2, a1, -241 ; RV64I-NEXT: lui a1, 4112 ; RV64I-NEXT: addi s3, a1, 257 ; RV64I-NEXT: .LBB4_1: # %bb2 ; RV64I-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64I-NEXT: call bar ; RV64I-NEXT: mv a1, a0 ; RV64I-NEXT: srli a0, a0, 1 ; RV64I-NEXT: and a0, a0, s0 ; RV64I-NEXT: sub a0, a1, a0 ; RV64I-NEXT: and a2, a0, s1 ; RV64I-NEXT: srli a0, a0, 2 ; RV64I-NEXT: and a0, a0, s1 ; RV64I-NEXT: add a0, a2, a0 ; RV64I-NEXT: srli a2, a0, 4 ; RV64I-NEXT: add a0, a0, a2 ; RV64I-NEXT: and a0, a0, s2 ; RV64I-NEXT: mul a0, a0, s3 ; RV64I-NEXT: srliw a0, a0, 24 ; RV64I-NEXT: bnez a1, .LBB4_1 ; RV64I-NEXT: # %bb.2: # %bb7 ; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload ; RV64I-NEXT: addi sp, sp, 48 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: test5: ; RV64ZBB: # %bb.0: # %bb ; RV64ZBB-NEXT: addi sp, sp, -16 ; RV64ZBB-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64ZBB-NEXT: sraw a0, a0, a1 ; RV64ZBB-NEXT: .LBB4_1: # %bb2 ; RV64ZBB-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64ZBB-NEXT: call bar ; RV64ZBB-NEXT: mv a1, a0 ; RV64ZBB-NEXT: cpopw a0, a0 ; RV64ZBB-NEXT: bnez a1, .LBB4_1 ; RV64ZBB-NEXT: # %bb.2: # %bb7 ; RV64ZBB-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64ZBB-NEXT: addi sp, sp, 16 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: test5: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sraw a1, a0, a1 ; NOREMOVAL-NEXT: .LBB4_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: cpopw a1, a0 ; NOREMOVAL-NEXT: bnez a0, .LBB4_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = tail call i32 @llvm.ctpop.i32(i32 %i4) %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare i32 @llvm.ctpop.i32(i32) define void @test6(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test6: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill ; CHECK-NEXT: sraw a0, a0, a1 ; CHECK-NEXT: fmv.w.x fs0, zero ; CHECK-NEXT: .LBB5_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: call baz ; CHECK-NEXT: feq.s a1, fa0, fs0 ; CHECK-NEXT: fcvt.w.s a0, fa0, rtz ; CHECK-NEXT: beqz a1, .LBB5_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test6: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill ; NOREMOVAL-NEXT: sraw a0, a0, a1 ; NOREMOVAL-NEXT: fmv.w.x fs0, zero ; NOREMOVAL-NEXT: .LBB5_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: call baz ; NOREMOVAL-NEXT: feq.s a1, fa0, fs0 ; NOREMOVAL-NEXT: fcvt.w.s a0, fa0, rtz ; NOREMOVAL-NEXT: beqz a1, .LBB5_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call float @baz(i32 signext %i3) %i5 = fptosi float %i4 to i32 %i6 = fcmp oeq float %i4, zeroinitializer br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare float @baz(i32 signext %i3) define void @test7(i32 signext %arg, i32 signext %arg1) nounwind { ; RV64I-LABEL: test7: ; RV64I: # %bb.0: # %bb ; RV64I-NEXT: addi sp, sp, -48 ; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill ; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: sraw a0, a0, a1 ; RV64I-NEXT: lui a1, 349525 ; RV64I-NEXT: addiw s0, a1, 1365 ; RV64I-NEXT: slli a1, s0, 32 ; RV64I-NEXT: add s0, s0, a1 ; RV64I-NEXT: lui a1, 209715 ; RV64I-NEXT: addiw s1, a1, 819 ; RV64I-NEXT: slli a1, s1, 32 ; RV64I-NEXT: add s1, s1, a1 ; RV64I-NEXT: lui a1, 61681 ; RV64I-NEXT: addiw s2, a1, -241 ; RV64I-NEXT: slli a1, s2, 32 ; RV64I-NEXT: add s2, s2, a1 ; RV64I-NEXT: lui a1, 4112 ; RV64I-NEXT: addiw s3, a1, 257 ; RV64I-NEXT: slli a1, s3, 32 ; RV64I-NEXT: add s3, s3, a1 ; RV64I-NEXT: .LBB6_1: # %bb2 ; RV64I-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64I-NEXT: call foo ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: and a1, a1, s0 ; RV64I-NEXT: sub a0, a0, a1 ; RV64I-NEXT: and a1, a0, s1 ; RV64I-NEXT: srli a0, a0, 2 ; RV64I-NEXT: and a0, a0, s1 ; RV64I-NEXT: add a0, a1, a0 ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: and a0, a0, s2 ; RV64I-NEXT: mul a0, a0, s3 ; RV64I-NEXT: srli a0, a0, 56 ; RV64I-NEXT: bnez a0, .LBB6_1 ; RV64I-NEXT: # %bb.2: # %bb7 ; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload ; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload ; RV64I-NEXT: addi sp, sp, 48 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: test7: ; RV64ZBB: # %bb.0: # %bb ; RV64ZBB-NEXT: addi sp, sp, -16 ; RV64ZBB-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64ZBB-NEXT: sraw a0, a0, a1 ; RV64ZBB-NEXT: .LBB6_1: # %bb2 ; RV64ZBB-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64ZBB-NEXT: call foo ; RV64ZBB-NEXT: cpop a0, a0 ; RV64ZBB-NEXT: bnez a0, .LBB6_1 ; RV64ZBB-NEXT: # %bb.2: # %bb7 ; RV64ZBB-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64ZBB-NEXT: addi sp, sp, 16 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: test7: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sraw a0, a0, a1 ; NOREMOVAL-NEXT: .LBB6_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: call foo ; NOREMOVAL-NEXT: cpop a0, a0 ; NOREMOVAL-NEXT: bnez a0, .LBB6_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i6, %bb2 ] %i4 = tail call signext i64 @foo(i32 signext %i3) %i5 = tail call i64 @llvm.ctpop.i64(i64 %i4) %i6 = trunc i64 %i5 to i32 %i7 = icmp eq i32 %i6, 0 br i1 %i7, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare i64 @llvm.ctpop.i64(i64) define void @test8(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test8: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: sraw a0, a0, a1 ; CHECK-NEXT: .LBB7_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: call foo ; CHECK-NEXT: ori a0, a0, -256 ; CHECK-NEXT: bnez a0, .LBB7_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test8: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sraw a0, a0, a1 ; NOREMOVAL-NEXT: .LBB7_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: call foo ; NOREMOVAL-NEXT: ori a0, a0, -256 ; NOREMOVAL-NEXT: bnez a0, .LBB7_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i6, %bb2 ] %i4 = tail call signext i64 @foo(i32 signext %i3) %i5 = or i64 %i4, -256 %i6 = trunc i64 %i5 to i32 %i7 = icmp eq i32 %i6, 0 br i1 %i7, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare i64 @foo(i32 signext) define void @test9(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test9: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 0(sp) # 8-byte Folded Spill ; CHECK-NEXT: sraw a0, a0, a1 ; CHECK-NEXT: li s0, 254 ; CHECK-NEXT: .LBB8_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: call bar ; CHECK-NEXT: mv a1, a0 ; CHECK-NEXT: slti a0, a0, 255 ; CHECK-NEXT: blt s0, a1, .LBB8_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 0(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test9: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 0(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sraw a1, a0, a1 ; NOREMOVAL-NEXT: li s0, 254 ; NOREMOVAL-NEXT: .LBB8_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: slti a1, a0, 255 ; NOREMOVAL-NEXT: blt s0, a0, .LBB8_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 0(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i7, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = icmp slt i32 %i4, 255 %i6 = sext i1 %i5 to i32 %i7 = sub i32 0, %i6 br i1 %i5, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } define void @test10(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test10: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill ; CHECK-NEXT: sraw a0, a0, a1 ; CHECK-NEXT: fmv.w.x fs0, zero ; CHECK-NEXT: .LBB9_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: call baz ; CHECK-NEXT: feq.s a1, fa0, fs0 ; CHECK-NEXT: fmv.x.w a0, fa0 ; CHECK-NEXT: beqz a1, .LBB9_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test10: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill ; NOREMOVAL-NEXT: sraw a0, a0, a1 ; NOREMOVAL-NEXT: fmv.w.x fs0, zero ; NOREMOVAL-NEXT: .LBB9_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: call baz ; NOREMOVAL-NEXT: feq.s a1, fa0, fs0 ; NOREMOVAL-NEXT: fmv.x.w a0, fa0 ; NOREMOVAL-NEXT: beqz a1, .LBB9_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %i = ashr i32 %arg, %arg1 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call float @baz(i32 signext %i3) %i5 = bitcast float %i4 to i32 %i6 = fcmp oeq float %i4, zeroinitializer br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } ; simple test for forward-searching. (and 1234) only uses lower word of input define signext i32 @test11(i64 %arg1, i64 %arg2, i64 %arg3) { ; CHECK-LABEL: test11: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addi a2, a2, -1 ; CHECK-NEXT: li a3, 256 ; CHECK-NEXT: .LBB10_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: andi a0, a0, 1234 ; CHECK-NEXT: addi a2, a2, 1 ; CHECK-NEXT: addw a0, a0, a1 ; CHECK-NEXT: bltu a2, a3, .LBB10_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test11: ; NOREMOVAL: # %bb.0: # %entry ; NOREMOVAL-NEXT: addi a2, a2, -1 ; NOREMOVAL-NEXT: li a3, 256 ; NOREMOVAL-NEXT: .LBB10_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: andi a0, a0, 1234 ; NOREMOVAL-NEXT: addi a2, a2, 1 ; NOREMOVAL-NEXT: add a0, a0, a1 ; NOREMOVAL-NEXT: bltu a2, a3, .LBB10_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret entry: br label %bb2 bb2: ; preds = %bb2, %entry %i1 = phi i64 [ %arg1, %entry ], [ %i5, %bb2 ] %i2 = phi i64 [ %arg3, %entry ], [ %i3, %bb2 ] %i3 = add i64 %i2, 1 %i4 = and i64 %i1, 1234 %i5 = add i64 %i4, %arg2 %i6 = icmp ugt i64 %i2, 255 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 %i7 = trunc i64 %i5 to i32 ret i32 %i7 } ; circular use-dependency and multiple transformations. define signext i32 @test12(i64 %arg1, i64 %arg2, i64 %arg3) { ; CHECK-LABEL: test12: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: li a4, 256 ; CHECK-NEXT: .LBB11_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: xor a0, a0, a1 ; CHECK-NEXT: mulw a2, a0, a1 ; CHECK-NEXT: addw a0, a0, a2 ; CHECK-NEXT: and a2, a2, a0 ; CHECK-NEXT: addi a3, a3, 1 ; CHECK-NEXT: add a0, a2, a1 ; CHECK-NEXT: bltu a3, a4, .LBB11_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: mv a0, a2 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test12: ; NOREMOVAL: # %bb.0: # %entry ; NOREMOVAL-NEXT: addi a2, a2, -1 ; NOREMOVAL-NEXT: li a3, 256 ; NOREMOVAL-NEXT: .LBB11_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: xor a0, a0, a1 ; NOREMOVAL-NEXT: mul a4, a0, a1 ; NOREMOVAL-NEXT: add a0, a0, a4 ; NOREMOVAL-NEXT: and a4, a4, a0 ; NOREMOVAL-NEXT: addi a2, a2, 1 ; NOREMOVAL-NEXT: add a0, a4, a1 ; NOREMOVAL-NEXT: bltu a2, a3, .LBB11_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: sext.w a0, a4 ; NOREMOVAL-NEXT: ret entry: br label %bb2 bb2: ; preds = %bb2, %entry %i1 = phi i64 [ %arg1, %entry ], [ %i6, %bb2 ] %i2 = phi i64 [ %arg3, %entry ], [ %i3, %bb2 ] %i3 = add i64 %i2, 1 %i4 = xor i64 %i1, %arg2 %i5 = mul i64 %i4, %arg2 %i9 = add i64 %i4, %i5 %i8 = and i64 %i5, %i9 %i6 = add i64 %i8, %arg2 %i7 = icmp ugt i64 %i2, 255 br i1 %i7, label %bb7, label %bb2 bb7: ; preds = %bb2 %r = trunc i64 %i8 to i32 ret i32 %r } ; Not optimized. sdiv doesn't only use lower word define signext i32 @test13(i64 %arg1, i64 %arg2, i64 %arg3) { ; CHECK-LABEL: test13: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addi a2, a2, -1 ; CHECK-NEXT: li a3, 256 ; CHECK-NEXT: .LBB12_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: div a0, a0, a1 ; CHECK-NEXT: addi a2, a2, 1 ; CHECK-NEXT: add a0, a0, a1 ; CHECK-NEXT: bltu a2, a3, .LBB12_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: sext.w a0, a0 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test13: ; NOREMOVAL: # %bb.0: # %entry ; NOREMOVAL-NEXT: addi a2, a2, -1 ; NOREMOVAL-NEXT: li a3, 256 ; NOREMOVAL-NEXT: .LBB12_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: div a0, a0, a1 ; NOREMOVAL-NEXT: addi a2, a2, 1 ; NOREMOVAL-NEXT: add a0, a0, a1 ; NOREMOVAL-NEXT: bltu a2, a3, .LBB12_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret entry: br label %bb2 bb2: ; preds = %bb2, %entry %i1 = phi i64 [ %arg1, %entry ], [ %i5, %bb2 ] %i2 = phi i64 [ %arg3, %entry ], [ %i3, %bb2 ] %i3 = add i64 %i2, 1 %i4 = sdiv i64 %i1, %arg2 %i5 = add i64 %i4, %arg2 %i6 = icmp ugt i64 %i2, 255 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 %i8 = trunc i64 %i5 to i32 ret i32 %i8 } ; int test14(int a, int n) { ; for (int i = 1; i < n; ++i) { ; if (a > 1000) ; return -1; ; a += i; ; } ; ; return a; ; } ; ; There should be no sext.w in the loop. define signext i32 @test14(i32 signext %0, i32 signext %1) { ; CHECK-LABEL: test14: ; CHECK: # %bb.0: ; CHECK-NEXT: li a2, 2 ; CHECK-NEXT: blt a1, a2, .LBB13_4 ; CHECK-NEXT: # %bb.1: # %.preheader ; CHECK-NEXT: li a2, 1 ; CHECK-NEXT: li a3, 1000 ; CHECK-NEXT: .LBB13_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: blt a3, a0, .LBB13_5 ; CHECK-NEXT: # %bb.3: # in Loop: Header=BB13_2 Depth=1 ; CHECK-NEXT: addw a0, a2, a0 ; CHECK-NEXT: addiw a2, a2, 1 ; CHECK-NEXT: blt a2, a1, .LBB13_2 ; CHECK-NEXT: .LBB13_4: ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB13_5: ; CHECK-NEXT: li a0, -1 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test14: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: li a2, 2 ; NOREMOVAL-NEXT: blt a1, a2, .LBB13_4 ; NOREMOVAL-NEXT: # %bb.1: # %.preheader ; NOREMOVAL-NEXT: li a2, 1 ; NOREMOVAL-NEXT: li a3, 1000 ; NOREMOVAL-NEXT: .LBB13_2: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a4, a0 ; NOREMOVAL-NEXT: blt a3, a4, .LBB13_5 ; NOREMOVAL-NEXT: # %bb.3: # in Loop: Header=BB13_2 Depth=1 ; NOREMOVAL-NEXT: addw a0, a2, a0 ; NOREMOVAL-NEXT: addiw a2, a2, 1 ; NOREMOVAL-NEXT: blt a2, a1, .LBB13_2 ; NOREMOVAL-NEXT: .LBB13_4: ; NOREMOVAL-NEXT: ret ; NOREMOVAL-NEXT: .LBB13_5: ; NOREMOVAL-NEXT: li a0, -1 ; NOREMOVAL-NEXT: ret %3 = icmp sgt i32 %1, 1 br i1 %3, label %4, label %12 4: ; preds = %2, %8 %5 = phi i32 [ %10, %8 ], [ 1, %2 ] %6 = phi i32 [ %9, %8 ], [ %0, %2 ] %7 = icmp sgt i32 %6, 1000 br i1 %7, label %12, label %8 8: ; preds = %4 %9 = add nsw i32 %5, %6 %10 = add nuw nsw i32 %5, 1 %11 = icmp slt i32 %10, %1 br i1 %11, label %4, label %12 12: ; preds = %8, %4, %2 %13 = phi i32 [ %0, %2 ], [ -1, %4 ], [ %9, %8 ] ret i32 %13 } ; Same as test14 but the signext attribute is missing from the argument so we ; can't optimize out the sext.w. define signext i32 @test14b(i32 %0, i32 signext %1) { ; CHECK-LABEL: test14b: ; CHECK: # %bb.0: ; CHECK-NEXT: li a2, 2 ; CHECK-NEXT: blt a1, a2, .LBB14_4 ; CHECK-NEXT: # %bb.1: # %.preheader ; CHECK-NEXT: li a2, 1 ; CHECK-NEXT: li a3, 1000 ; CHECK-NEXT: .LBB14_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: sext.w a4, a0 ; CHECK-NEXT: blt a3, a4, .LBB14_5 ; CHECK-NEXT: # %bb.3: # in Loop: Header=BB14_2 Depth=1 ; CHECK-NEXT: add a0, a2, a0 ; CHECK-NEXT: addiw a2, a2, 1 ; CHECK-NEXT: blt a2, a1, .LBB14_2 ; CHECK-NEXT: .LBB14_4: ; CHECK-NEXT: sext.w a0, a0 ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB14_5: ; CHECK-NEXT: li a0, -1 ; CHECK-NEXT: sext.w a0, a0 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test14b: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: li a2, 2 ; NOREMOVAL-NEXT: blt a1, a2, .LBB14_4 ; NOREMOVAL-NEXT: # %bb.1: # %.preheader ; NOREMOVAL-NEXT: li a2, 1 ; NOREMOVAL-NEXT: li a3, 1000 ; NOREMOVAL-NEXT: .LBB14_2: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a4, a0 ; NOREMOVAL-NEXT: blt a3, a4, .LBB14_5 ; NOREMOVAL-NEXT: # %bb.3: # in Loop: Header=BB14_2 Depth=1 ; NOREMOVAL-NEXT: add a0, a2, a0 ; NOREMOVAL-NEXT: addiw a2, a2, 1 ; NOREMOVAL-NEXT: blt a2, a1, .LBB14_2 ; NOREMOVAL-NEXT: .LBB14_4: ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret ; NOREMOVAL-NEXT: .LBB14_5: ; NOREMOVAL-NEXT: li a0, -1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret %3 = icmp sgt i32 %1, 1 br i1 %3, label %4, label %12 4: ; preds = %2, %8 %5 = phi i32 [ %10, %8 ], [ 1, %2 ] %6 = phi i32 [ %9, %8 ], [ %0, %2 ] %7 = icmp sgt i32 %6, 1000 br i1 %7, label %12, label %8 8: ; preds = %4 %9 = add nsw i32 %5, %6 %10 = add nuw nsw i32 %5, 1 %11 = icmp slt i32 %10, %1 br i1 %11, label %4, label %12 12: ; preds = %8, %4, %2 %13 = phi i32 [ %0, %2 ], [ -1, %4 ], [ %9, %8 ] ret i32 %13 } ; Same as test14, but the argument is zero extended instead of sign extended so ; we can't optimize it. define signext i32 @test14c(i32 zeroext %0, i32 signext %1) { ; CHECK-LABEL: test14c: ; CHECK: # %bb.0: ; CHECK-NEXT: li a2, 2 ; CHECK-NEXT: blt a1, a2, .LBB15_4 ; CHECK-NEXT: # %bb.1: # %.preheader ; CHECK-NEXT: li a2, 1 ; CHECK-NEXT: li a3, 1000 ; CHECK-NEXT: .LBB15_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: sext.w a4, a0 ; CHECK-NEXT: blt a3, a4, .LBB15_5 ; CHECK-NEXT: # %bb.3: # in Loop: Header=BB15_2 Depth=1 ; CHECK-NEXT: add a0, a2, a0 ; CHECK-NEXT: addiw a2, a2, 1 ; CHECK-NEXT: blt a2, a1, .LBB15_2 ; CHECK-NEXT: .LBB15_4: ; CHECK-NEXT: sext.w a0, a0 ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB15_5: ; CHECK-NEXT: li a0, -1 ; CHECK-NEXT: sext.w a0, a0 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test14c: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: li a2, 2 ; NOREMOVAL-NEXT: blt a1, a2, .LBB15_4 ; NOREMOVAL-NEXT: # %bb.1: # %.preheader ; NOREMOVAL-NEXT: li a2, 1 ; NOREMOVAL-NEXT: li a3, 1000 ; NOREMOVAL-NEXT: .LBB15_2: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a4, a0 ; NOREMOVAL-NEXT: blt a3, a4, .LBB15_5 ; NOREMOVAL-NEXT: # %bb.3: # in Loop: Header=BB15_2 Depth=1 ; NOREMOVAL-NEXT: add a0, a2, a0 ; NOREMOVAL-NEXT: addiw a2, a2, 1 ; NOREMOVAL-NEXT: blt a2, a1, .LBB15_2 ; NOREMOVAL-NEXT: .LBB15_4: ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret ; NOREMOVAL-NEXT: .LBB15_5: ; NOREMOVAL-NEXT: li a0, -1 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret %3 = icmp sgt i32 %1, 1 br i1 %3, label %4, label %12 4: ; preds = %2, %8 %5 = phi i32 [ %10, %8 ], [ 1, %2 ] %6 = phi i32 [ %9, %8 ], [ %0, %2 ] %7 = icmp sgt i32 %6, 1000 br i1 %7, label %12, label %8 8: ; preds = %4 %9 = add nsw i32 %5, %6 %10 = add nuw nsw i32 %5, 1 %11 = icmp slt i32 %10, %1 br i1 %11, label %4, label %12 12: ; preds = %8, %4, %2 %13 = phi i32 [ %0, %2 ], [ -1, %4 ], [ %9, %8 ] ret i32 %13 } ; Same as test14 but the argument is zero extended from i31. Since bits 63:31 ; are zero, this counts as an i32 sign extend so we can optimize it. define signext i32 @test14d(i31 zeroext %0, i32 signext %1) { ; CHECK-LABEL: test14d: ; CHECK: # %bb.0: ; CHECK-NEXT: li a2, 2 ; CHECK-NEXT: blt a1, a2, .LBB16_4 ; CHECK-NEXT: # %bb.1: # %.preheader ; CHECK-NEXT: li a2, 1 ; CHECK-NEXT: li a3, 1000 ; CHECK-NEXT: .LBB16_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: blt a3, a0, .LBB16_5 ; CHECK-NEXT: # %bb.3: # in Loop: Header=BB16_2 Depth=1 ; CHECK-NEXT: addw a0, a2, a0 ; CHECK-NEXT: addiw a2, a2, 1 ; CHECK-NEXT: blt a2, a1, .LBB16_2 ; CHECK-NEXT: .LBB16_4: ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB16_5: ; CHECK-NEXT: li a0, -1 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test14d: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: li a2, 2 ; NOREMOVAL-NEXT: blt a1, a2, .LBB16_4 ; NOREMOVAL-NEXT: # %bb.1: # %.preheader ; NOREMOVAL-NEXT: li a2, 1 ; NOREMOVAL-NEXT: li a3, 1000 ; NOREMOVAL-NEXT: .LBB16_2: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a4, a0 ; NOREMOVAL-NEXT: blt a3, a4, .LBB16_5 ; NOREMOVAL-NEXT: # %bb.3: # in Loop: Header=BB16_2 Depth=1 ; NOREMOVAL-NEXT: addw a0, a2, a0 ; NOREMOVAL-NEXT: addiw a2, a2, 1 ; NOREMOVAL-NEXT: blt a2, a1, .LBB16_2 ; NOREMOVAL-NEXT: .LBB16_4: ; NOREMOVAL-NEXT: ret ; NOREMOVAL-NEXT: .LBB16_5: ; NOREMOVAL-NEXT: li a0, -1 ; NOREMOVAL-NEXT: ret %zext = zext i31 %0 to i32 %3 = icmp sgt i32 %1, 1 br i1 %3, label %4, label %12 4: ; preds = %2, %8 %5 = phi i32 [ %10, %8 ], [ 1, %2 ] %6 = phi i32 [ %9, %8 ], [ %zext, %2 ] %7 = icmp sgt i32 %6, 1000 br i1 %7, label %12, label %8 8: ; preds = %4 %9 = add nsw i32 %5, %6 %10 = add nuw nsw i32 %5, 1 %11 = icmp slt i32 %10, %1 br i1 %11, label %4, label %12 12: ; preds = %8, %4, %2 %13 = phi i32 [ %zext, %2 ], [ -1, %4 ], [ %9, %8 ] ret i32 %13 } define signext i32 @test15(i64 %arg1, i64 %arg2, i64 %arg3, ptr %arg4) { ; CHECK-LABEL: test15: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addi a2, a2, -1 ; CHECK-NEXT: li a4, 256 ; CHECK-NEXT: .LBB17_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: andi a0, a0, 1234 ; CHECK-NEXT: addw a0, a0, a1 ; CHECK-NEXT: addi a2, a2, 1 ; CHECK-NEXT: sw a0, 0(a3) ; CHECK-NEXT: bltu a2, a4, .LBB17_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test15: ; NOREMOVAL: # %bb.0: # %entry ; NOREMOVAL-NEXT: addi a2, a2, -1 ; NOREMOVAL-NEXT: li a4, 256 ; NOREMOVAL-NEXT: .LBB17_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: andi a0, a0, 1234 ; NOREMOVAL-NEXT: add a0, a0, a1 ; NOREMOVAL-NEXT: addi a2, a2, 1 ; NOREMOVAL-NEXT: sw a0, 0(a3) ; NOREMOVAL-NEXT: bltu a2, a4, .LBB17_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret entry: br label %bb2 bb2: ; preds = %bb2, %entry %i1 = phi i64 [ %arg1, %entry ], [ %i5, %bb2 ] %i2 = phi i64 [ %arg3, %entry ], [ %i3, %bb2 ] %i3 = add i64 %i2, 1 %i4 = and i64 %i1, 1234 %i5 = add i64 %i4, %arg2 %i8 = trunc i64 %i5 to i32 store i32 %i8, ptr %arg4 %i6 = icmp ugt i64 %i2, 255 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 %i7 = trunc i64 %i5 to i32 ret i32 %i7 } ; This test previously removed a sext.w without converting a slli to slliw. define signext i32 @bug(i32 signext %x) { ; CHECK-LABEL: bug: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: beqz a0, .LBB18_4 ; CHECK-NEXT: # %bb.1: # %if.end ; CHECK-NEXT: srliw a2, a0, 16 ; CHECK-NEXT: seqz a1, a2 ; CHECK-NEXT: slli a1, a1, 4 ; CHECK-NEXT: sllw a1, a0, a1 ; CHECK-NEXT: li a0, 16 ; CHECK-NEXT: beqz a2, .LBB18_3 ; CHECK-NEXT: # %bb.2: # %if.end ; CHECK-NEXT: li a0, 32 ; CHECK-NEXT: .LBB18_3: # %if.end ; CHECK-NEXT: srliw a2, a1, 24 ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 3 ; CHECK-NEXT: sllw a1, a1, a3 ; CHECK-NEXT: neg a2, a2 ; CHECK-NEXT: andi a2, a2, -8 ; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: srliw a2, a1, 28 ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 2 ; CHECK-NEXT: sllw a1, a1, a3 ; CHECK-NEXT: neg a2, a2 ; CHECK-NEXT: andi a2, a2, -4 ; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: srliw a2, a1, 30 ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 1 ; CHECK-NEXT: sllw a1, a1, a3 ; CHECK-NEXT: neg a2, a2 ; CHECK-NEXT: andi a2, a2, -2 ; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: srai a1, a1, 31 ; CHECK-NEXT: not a1, a1 ; CHECK-NEXT: addw a0, a0, a1 ; CHECK-NEXT: .LBB18_4: # %cleanup ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: bug: ; NOREMOVAL: # %bb.0: # %entry ; NOREMOVAL-NEXT: beqz a0, .LBB18_4 ; NOREMOVAL-NEXT: # %bb.1: # %if.end ; NOREMOVAL-NEXT: srliw a2, a0, 16 ; NOREMOVAL-NEXT: seqz a1, a2 ; NOREMOVAL-NEXT: slli a1, a1, 4 ; NOREMOVAL-NEXT: sllw a1, a0, a1 ; NOREMOVAL-NEXT: li a0, 16 ; NOREMOVAL-NEXT: beqz a2, .LBB18_3 ; NOREMOVAL-NEXT: # %bb.2: # %if.end ; NOREMOVAL-NEXT: li a0, 32 ; NOREMOVAL-NEXT: .LBB18_3: # %if.end ; NOREMOVAL-NEXT: srliw a2, a1, 24 ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 3 ; NOREMOVAL-NEXT: sllw a1, a1, a3 ; NOREMOVAL-NEXT: neg a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -8 ; NOREMOVAL-NEXT: add a0, a0, a2 ; NOREMOVAL-NEXT: srliw a2, a1, 28 ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 2 ; NOREMOVAL-NEXT: sllw a1, a1, a3 ; NOREMOVAL-NEXT: neg a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -4 ; NOREMOVAL-NEXT: add a0, a0, a2 ; NOREMOVAL-NEXT: srliw a2, a1, 30 ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 1 ; NOREMOVAL-NEXT: sllw a1, a1, a3 ; NOREMOVAL-NEXT: neg a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -2 ; NOREMOVAL-NEXT: add a0, a0, a2 ; NOREMOVAL-NEXT: srai a1, a1, 31 ; NOREMOVAL-NEXT: not a1, a1 ; NOREMOVAL-NEXT: add a0, a0, a1 ; NOREMOVAL-NEXT: .LBB18_4: # %cleanup ; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret entry: %tobool.not = icmp eq i32 %x, 0 br i1 %tobool.not, label %cleanup, label %if.end if.end: ; preds = %entry %tobool1.not = icmp ult i32 %x, 65536 %shl = shl i32 %x, 16 %spec.select = select i1 %tobool1.not, i32 %shl, i32 %x %spec.select43 = select i1 %tobool1.not, i32 16, i32 32 %tobool5.not = icmp ult i32 %spec.select, 16777216 %shl7 = shl i32 %spec.select, 8 %sub8 = add nsw i32 %spec.select43, -8 %x.addr.1 = select i1 %tobool5.not, i32 %shl7, i32 %spec.select %r.1 = select i1 %tobool5.not, i32 %sub8, i32 %spec.select43 %tobool11.not = icmp ult i32 %x.addr.1, 268435456 %shl13 = shl i32 %x.addr.1, 4 %sub14 = add nsw i32 %r.1, -4 %x.addr.2 = select i1 %tobool11.not, i32 %shl13, i32 %x.addr.1 %r.2 = select i1 %tobool11.not, i32 %sub14, i32 %r.1 %tobool17.not = icmp ult i32 %x.addr.2, 1073741824 %shl19 = shl i32 %x.addr.2, 2 %sub20 = add nsw i32 %r.2, -2 %x.addr.3 = select i1 %tobool17.not, i32 %shl19, i32 %x.addr.2 %r.3 = select i1 %tobool17.not, i32 %sub20, i32 %r.2 %x.addr.3.lobit = ashr i32 %x.addr.3, 31 %x.addr.3.lobit.not = xor i32 %x.addr.3.lobit, -1 %r.4 = add nsw i32 %r.3, %x.addr.3.lobit.not br label %cleanup cleanup: ; preds = %entry, %if.end %retval.0 = phi i32 [ %r.4, %if.end ], [ 0, %entry ] ret i32 %retval.0 } define void @test16(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test16: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: mv s0, a1 ; CHECK-NEXT: call bar ; CHECK-NEXT: mv s1, a0 ; CHECK-NEXT: .LBB19_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: mv a0, s1 ; CHECK-NEXT: call bar ; CHECK-NEXT: sllw s1, s1, s0 ; CHECK-NEXT: bnez a0, .LBB19_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test16: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -32 ; NOREMOVAL-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: mv s0, a1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: mv s1, a0 ; NOREMOVAL-NEXT: .LBB19_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, s1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: sllw s1, s1, s0 ; NOREMOVAL-NEXT: bnez a0, .LBB19_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 32 ; NOREMOVAL-NEXT: ret bb: %i = call signext i32 @bar(i32 signext %arg) br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = shl i32 %i3, %arg1 %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } define void @test17(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test17: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: mv s0, a1 ; CHECK-NEXT: call bat ; CHECK-NEXT: mv s1, a0 ; CHECK-NEXT: .LBB20_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: mv a0, s1 ; CHECK-NEXT: call bar ; CHECK-NEXT: sllw s1, s1, s0 ; CHECK-NEXT: bnez a0, .LBB20_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test17: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -32 ; NOREMOVAL-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: mv s0, a1 ; NOREMOVAL-NEXT: call bat ; NOREMOVAL-NEXT: mv s1, a0 ; NOREMOVAL-NEXT: .LBB20_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, s1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: sllw s1, s1, s0 ; NOREMOVAL-NEXT: bnez a0, .LBB20_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 32 ; NOREMOVAL-NEXT: ret bb: %i = call zeroext i16 @bat(i32 signext %arg) %zext = zext i16 %i to i32 br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %zext, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = shl i32 %i3, %arg1 %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare zeroext i16 @bat(i32 signext) define void @test18(i32 signext %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test18: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: mv s0, a1 ; CHECK-NEXT: sha256sig0 s1, a1 ; CHECK-NEXT: .LBB21_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: mv a0, s1 ; CHECK-NEXT: call bar ; CHECK-NEXT: sllw s1, s1, s0 ; CHECK-NEXT: bnez a0, .LBB21_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test18: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -32 ; NOREMOVAL-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: mv s0, a1 ; NOREMOVAL-NEXT: sha256sig0 s1, a1 ; NOREMOVAL-NEXT: .LBB21_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, s1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: sllw s1, s1, s0 ; NOREMOVAL-NEXT: bnez a0, .LBB21_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 32 ; NOREMOVAL-NEXT: ret bb: %i = call i32 @llvm.riscv.sha256sig0(i32 %arg1) br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = shl i32 %i3, %arg1 %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare i32 @llvm.riscv.sha256sig0(i32) ; The type promotion of %7 forms a sext_inreg, but %7 and %6 are combined to ; form a sh2add. This leaves behind a sext.w that isn't needed. define signext i32 @sextw_sh2add(i1 zeroext %0, ptr %1, i32 signext %2, i32 signext %3, i32 signext %4) { ; RV64I-LABEL: sextw_sh2add: ; RV64I: # %bb.0: ; RV64I-NEXT: slli a2, a2, 2 ; RV64I-NEXT: add a3, a2, a3 ; RV64I-NEXT: beqz a0, .LBB22_2 ; RV64I-NEXT: # %bb.1: ; RV64I-NEXT: sw a3, 0(a1) ; RV64I-NEXT: .LBB22_2: ; RV64I-NEXT: addw a0, a3, a4 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: sextw_sh2add: ; RV64ZBB: # %bb.0: ; RV64ZBB-NEXT: sh2add a2, a2, a3 ; RV64ZBB-NEXT: beqz a0, .LBB22_2 ; RV64ZBB-NEXT: # %bb.1: ; RV64ZBB-NEXT: sw a2, 0(a1) ; RV64ZBB-NEXT: .LBB22_2: ; RV64ZBB-NEXT: addw a0, a2, a4 ; RV64ZBB-NEXT: ret ; ; NOREMOVAL-LABEL: sextw_sh2add: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: sh2add a2, a2, a3 ; NOREMOVAL-NEXT: mv a2, a2 ; NOREMOVAL-NEXT: beqz a0, .LBB22_2 ; NOREMOVAL-NEXT: # %bb.1: ; NOREMOVAL-NEXT: sw a2, 0(a1) ; NOREMOVAL-NEXT: .LBB22_2: ; NOREMOVAL-NEXT: addw a0, a2, a4 ; NOREMOVAL-NEXT: ret %6 = shl i32 %2, 2 %7 = add i32 %6, %3 br i1 %0, label %8, label %9 8: ; preds = %5 store i32 %7, ptr %1, align 4 br label %9 9: ; preds = %5, %8 %10 = add i32 %7, %4 ret i32 %10 } ; Negative test - an explicit sext.w *is* required define signext i32 @test19(i64 %arg, i1 zeroext %c1, i1 zeroext %c2, ptr %p) nounwind { ; CHECK-LABEL: test19: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 0(sp) # 8-byte Folded Spill ; CHECK-NEXT: neg a0, a1 ; CHECK-NEXT: li a1, 1 ; CHECK-NEXT: slli a1, a1, 32 ; CHECK-NEXT: addi s0, a1, 35 ; CHECK-NEXT: and s0, a0, s0 ; CHECK-NEXT: sd s0, 0(a3) ; CHECK-NEXT: beqz a2, .LBB23_2 ; CHECK-NEXT: # %bb.1: # %bb2 ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: call bar ; CHECK-NEXT: mv s0, a0 ; CHECK-NEXT: .LBB23_2: # %bb7 ; CHECK-NEXT: call side_effect ; CHECK-NEXT: sext.w a0, s0 ; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 0(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test19: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -16 ; NOREMOVAL-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 0(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: neg a0, a1 ; NOREMOVAL-NEXT: li a1, 1 ; NOREMOVAL-NEXT: slli a1, a1, 32 ; NOREMOVAL-NEXT: addi s0, a1, 35 ; NOREMOVAL-NEXT: and s0, a0, s0 ; NOREMOVAL-NEXT: sd s0, 0(a3) ; NOREMOVAL-NEXT: beqz a2, .LBB23_2 ; NOREMOVAL-NEXT: # %bb.1: # %bb2 ; NOREMOVAL-NEXT: li a0, 0 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: mv s0, a0 ; NOREMOVAL-NEXT: .LBB23_2: # %bb7 ; NOREMOVAL-NEXT: call side_effect ; NOREMOVAL-NEXT: sext.w a0, s0 ; NOREMOVAL-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 0(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 16 ; NOREMOVAL-NEXT: ret bb: %sel = select i1 %c1, i64 4294967331, i64 0 store i64 %sel, ptr %p, align 8 br i1 %c2, label %bb2, label %bb7 bb2: ; preds = %bb2, %bb %i4 = call signext i32 @bar(i32 0) %i4.sext = sext i32 %i4 to i64 br label %bb7 bb7: ; preds = %bb2 %phi = phi i64 [ %sel, %bb ], [ %i4.sext, %bb2 ] %trunc = trunc i64 %phi to i32 call void @side_effect() ret i32 %trunc } declare void @side_effect(i64) define void @test20( %arg, i32 signext %arg1) nounwind { ; CHECK-LABEL: test20: ; CHECK: # %bb.0: # %bb ; CHECK-NEXT: addi sp, sp, -32 ; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; CHECK-NEXT: mv s0, a0 ; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma ; CHECK-NEXT: vmv.x.s s1, v8 ; CHECK-NEXT: .LBB24_1: # %bb2 ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: mv a0, s1 ; CHECK-NEXT: call bar ; CHECK-NEXT: sllw s1, s1, s0 ; CHECK-NEXT: bnez a0, .LBB24_1 ; CHECK-NEXT: # %bb.2: # %bb7 ; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret ; ; NOREMOVAL-LABEL: test20: ; NOREMOVAL: # %bb.0: # %bb ; NOREMOVAL-NEXT: addi sp, sp, -32 ; NOREMOVAL-NEXT: sd ra, 24(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s0, 16(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: sd s1, 8(sp) # 8-byte Folded Spill ; NOREMOVAL-NEXT: mv s0, a0 ; NOREMOVAL-NEXT: vsetivli zero, 1, e32, m1, ta, ma ; NOREMOVAL-NEXT: vmv.x.s s1, v8 ; NOREMOVAL-NEXT: .LBB24_1: # %bb2 ; NOREMOVAL-NEXT: # =>This Inner Loop Header: Depth=1 ; NOREMOVAL-NEXT: sext.w a0, s1 ; NOREMOVAL-NEXT: call bar ; NOREMOVAL-NEXT: sllw s1, s1, s0 ; NOREMOVAL-NEXT: bnez a0, .LBB24_1 ; NOREMOVAL-NEXT: # %bb.2: # %bb7 ; NOREMOVAL-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; NOREMOVAL-NEXT: addi sp, sp, 32 ; NOREMOVAL-NEXT: ret bb: %i = call i32 @llvm.riscv.vmv.x.s.nxv1i32( %arg) br label %bb2 bb2: ; preds = %bb2, %bb %i3 = phi i32 [ %i, %bb ], [ %i5, %bb2 ] %i4 = tail call signext i32 @bar(i32 signext %i3) %i5 = shl i32 %i3, %arg1 %i6 = icmp eq i32 %i4, 0 br i1 %i6, label %bb7, label %bb2 bb7: ; preds = %bb2 ret void } declare i32 @llvm.riscv.vmv.x.s.nxv1i32( )