Skip to content

Commit 11be11b

Browse files
dtcxzywtru
authored andcommitted
[SCEV] Fix sext handling for getConstantMultiple (#117093)
Counterexample: 219 is a multiple of 73. But `sext i8 219 to i16 = 65499` is not. Fixes #116483. (cherry picked from commit 458dfbd)
1 parent 336f877 commit 11be11b

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6313,8 +6313,10 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
63136313
return getConstantMultiple(Z->getOperand()).zext(BitWidth);
63146314
}
63156315
case scSignExtend: {
6316+
// Only multiples that are a power of 2 will hold after sext.
63166317
const SCEVSignExtendExpr *E = cast<SCEVSignExtendExpr>(S);
6317-
return getConstantMultiple(E->getOperand()).sext(BitWidth);
6318+
uint32_t TZ = getMinTrailingZeros(E->getOperand());
6319+
return GetShiftedByZeros(TZ);
63186320
}
63196321
case scMulExpr: {
63206322
const SCEVMulExpr *M = cast<SCEVMulExpr>(S);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -disable-output "-passes=print<scalar-evolution>" < %s 2>&1 | FileCheck %s
3+
4+
define i16 @test() {
5+
; CHECK-LABEL: 'test'
6+
; CHECK-NEXT: Classifying expressions for: @test
7+
; CHECK-NEXT: %xor = xor i32 0, 3
8+
; CHECK-NEXT: --> %xor U: [3,4) S: [3,4)
9+
; CHECK-NEXT: %mul = mul i32 %xor, 329
10+
; CHECK-NEXT: --> (329 * %xor)<nuw><nsw> U: [987,988) S: [987,988)
11+
; CHECK-NEXT: %conv = trunc i32 %mul to i16
12+
; CHECK-NEXT: --> (329 * (trunc i32 %xor to i16))<nuw><nsw> U: [987,988) S: [987,988)
13+
; CHECK-NEXT: %sext = shl i16 %conv, 8
14+
; CHECK-NEXT: --> (18688 * (trunc i32 %xor to i16))<nuw> U: [-9472,-9471) S: [-9472,-9471)
15+
; CHECK-NEXT: %conv1 = ashr i16 %sext, 8
16+
; CHECK-NEXT: --> (sext i8 (73 * (trunc i32 %xor to i8))<nuw> to i16) U: [-37,-36) S: [-37,-36)
17+
; CHECK-NEXT: Determining loop execution counts for: @test
18+
;
19+
entry:
20+
%xor = xor i32 0, 3
21+
%mul = mul i32 %xor, 329
22+
%conv = trunc i32 %mul to i16
23+
%sext = shl i16 %conv, 8
24+
%conv1 = ashr i16 %sext, 8
25+
ret i16 %conv1
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=indvars < %s | FileCheck %s
3+
4+
define i32 @test() {
5+
; CHECK-LABEL: define i32 @test() {
6+
; CHECK-NEXT: [[ENTRY:.*:]]
7+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 0, 3
8+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[XOR]], 329
9+
; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[MUL]] to i16
10+
; CHECK-NEXT: [[SEXT:%.*]] = shl i16 [[CONV]], 8
11+
; CHECK-NEXT: [[CONV1:%.*]] = ashr i16 [[SEXT]], 8
12+
; CHECK-NEXT: br label %[[LOOP_BODY:.*]]
13+
; CHECK: [[LOOP_BODY]]:
14+
; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP_BODY]]
15+
; CHECK: [[EXIT]]:
16+
; CHECK-NEXT: [[CONV3:%.*]] = zext i16 [[CONV1]] to i32
17+
; CHECK-NEXT: ret i32 [[CONV3]]
18+
;
19+
entry:
20+
%xor = xor i32 0, 3
21+
%mul = mul i32 %xor, 329
22+
%conv = trunc i32 %mul to i16
23+
%sext = shl i16 %conv, 8
24+
%conv1 = ashr i16 %sext, 8
25+
%conv3 = zext i16 %conv1 to i32
26+
br label %loop.body
27+
28+
loop.body:
29+
%indvar = phi i32 [ %indvar.inc, %loop.body ], [ 1, %entry ]
30+
%indvar.inc = add nuw i32 %indvar, 1
31+
%exitcond = icmp eq i32 %indvar, %conv3
32+
br i1 %exitcond, label %exit, label %loop.body
33+
34+
exit:
35+
ret i32 %conv3
36+
}

0 commit comments

Comments
 (0)