[llvm] [TypePromotion] Do not zero-extend getelementptr indexes since signed (PR #134281)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 3 10:27:45 PDT 2025
https://github.com/antoniofrighetto created https://github.com/llvm/llvm-project/pull/134281
A miscompilation issue has been addressed with improved handling.
Fixes: https://github.com/llvm/llvm-project/issues/133928.
Alive2 for signext_bitcast_phi_select test: https://alive2.llvm.org/ce/z/gcMNvS.
>From f3eb0aec22a4b84c1a06a0b7cf61d7353bd70ee5 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 3 Apr 2025 19:15:50 +0200
Subject: [PATCH] [TypePromotion] Do not zero-extend getelementptr indexes
since signed
A miscompilation issue has been addressed with improved handling.
Fixes: https://github.com/llvm/llvm-project/issues/133928.
Alive2: https://alive2.llvm.org/ce/z/gcMNvS.
---
llvm/lib/CodeGen/TypePromotion.cpp | 2 +-
.../CodeGen/AArch64/typepromotion-phisret.ll | 22 ++++++++-------
.../Transforms/TypePromotion/ARM/phis-ret.ll | 18 +++++-------
.../Transforms/TypePromotion/ARM/pointers.ll | 28 ++++++++-----------
4 files changed, 32 insertions(+), 38 deletions(-)
diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp
index b1f99094daa4a..01db72cbb8e85 100644
--- a/llvm/lib/CodeGen/TypePromotion.cpp
+++ b/llvm/lib/CodeGen/TypePromotion.cpp
@@ -809,7 +809,7 @@ bool TypePromotionImpl::TryToPromote(Value *V, unsigned PromotedWidth,
// Ignore GEPs because they don't need promoting and the constant indices
// will prevent the transformation.
if (isa<GetElementPtrInst>(V))
- return true;
+ return false;
if (!isSupportedValue(V) || (shouldPromote(V) && !isLegalToPromote(V))) {
LLVM_DEBUG(dbgs() << "IR Promotion: Can't handle: " << *V << "\n");
diff --git a/llvm/test/CodeGen/AArch64/typepromotion-phisret.ll b/llvm/test/CodeGen/AArch64/typepromotion-phisret.ll
index d60578b7bafe4..a9164312b99cc 100644
--- a/llvm/test/CodeGen/AArch64/typepromotion-phisret.ll
+++ b/llvm/test/CodeGen/AArch64/typepromotion-phisret.ll
@@ -237,25 +237,27 @@ define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, ptr %res) {
define i16 @signext_bitcast_phi_select(i16 signext %start, ptr %in) {
; CHECK-LABEL: signext_bitcast_phi_select:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov w8, #-1 // =0xffffffff
-; CHECK-NEXT: and w9, w0, #0xffff
-; CHECK-NEXT: cmp w8, w9, sxth
+; CHECK-NEXT: mov w9, #-1 // =0xffffffff
+; CHECK-NEXT: mov w10, #32768 // =0x8000
+; 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, w9, sxtw #1]
-; CHECK-NEXT: cmp w0, w9
+; 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, w9, #15
-; CHECK-NEXT: eor w10, w10, #0x1
-; CHECK-NEXT: add w9, w10, w9
-; CHECK-NEXT: cmp w8, w9, sxth
+; CHECK-NEXT: bic w8, w10, w0
+; 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
diff --git a/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll b/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
index 6f41742e66e53..d3ba82460a18a 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
@@ -293,28 +293,24 @@ define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, ptr %res) {
define i16 @signext_bitcast_phi_select(i16 signext %start, ptr %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: [[TMP1:%.*]] = phi i16 [ [[SELECT:%.*]], [[IF_ELSE:%.*]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i16 [[TMP1]], [[CONST]]
; CHECK-NEXT: br i1 [[CMP_I]], label [[EXIT:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: [[IDX_NEXT:%.*]] = getelementptr i16, ptr [[IN:%.*]], i32 [[IDX]]
+; CHECK-NEXT: [[IDX_NEXT:%.*]] = getelementptr i16, ptr [[IN:%.*]], i16 [[TMP1]]
; CHECK-NEXT: [[LD:%.*]] = load i16, ptr [[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]], [[TMP1]]
; 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 [[TMP1]], 15
+; CHECK-NEXT: [[LOBIT_NOT:%.*]] = xor i16 [[LOBIT]], 1
+; CHECK-NEXT: [[SELECT]] = add nuw i16 [[LOBIT_NOT]], [[TMP1]]
; 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: [[TMP3:%.*]] = phi i16 [ [[LD]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ]
; CHECK-NEXT: ret i16 [[TMP3]]
;
entry:
diff --git a/llvm/test/Transforms/TypePromotion/ARM/pointers.ll b/llvm/test/Transforms/TypePromotion/ARM/pointers.ll
index 362b4ec73401c..187fc8b7267b8 100644
--- a/llvm/test/Transforms/TypePromotion/ARM/pointers.ll
+++ b/llvm/test/Transforms/TypePromotion/ARM/pointers.ll
@@ -4,20 +4,18 @@
define void @phi_pointers(ptr %a, ptr %b, i8 zeroext %M, i8 zeroext %N) {
; CHECK-LABEL: @phi_pointers(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[M:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[N:%.*]] to i32
-; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[TMP0]], 1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], [[TMP1]]
+; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[M:%.*]], 1
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[ADD]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD]], [[N:%.*]]
; CHECK-NEXT: [[BASE:%.*]] = select i1 [[CMP]], ptr [[A:%.*]], ptr [[B:%.*]]
; CHECK-NEXT: [[OTHER:%.*]] = select i1 [[CMP]], ptr [[B]], ptr [[B]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[BASE]], [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[AND]], [[ENTRY]] ], [ [[INC:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[AND]], [[ENTRY]] ], [ [[INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[PTR]], align 2
-; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IDX]], 1
-; CHECK-NEXT: [[GEP]] = getelementptr inbounds i16, ptr [[PTR]], i32 [[INC]]
+; CHECK-NEXT: [[INC]] = add nuw nsw i8 [[IDX]], 1
+; CHECK-NEXT: [[GEP]] = getelementptr inbounds i16, ptr [[PTR]], i8 [[INC]]
; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[GEP]], [[OTHER]]
; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
@@ -47,11 +45,9 @@ exit:
define void @phi_pointers_null(ptr %a, ptr %b, i8 zeroext %M, i8 zeroext %N) {
; CHECK-LABEL: @phi_pointers_null(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[M:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[N:%.*]] to i32
-; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[TMP0]], 1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], [[TMP1]]
+; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[M:%.*]], 1
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[ADD]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD]], [[N:%.*]]
; CHECK-NEXT: [[BASE:%.*]] = select i1 [[CMP]], ptr [[A:%.*]], ptr [[B:%.*]]
; CHECK-NEXT: [[OTHER:%.*]] = select i1 [[CMP]], ptr [[B]], ptr [[B]]
; CHECK-NEXT: [[CMP_1:%.*]] = icmp eq ptr [[BASE]], [[OTHER]]
@@ -60,13 +56,13 @@ define void @phi_pointers_null(ptr %a, ptr %b, i8 zeroext %M, i8 zeroext %N) {
; CHECK-NEXT: br label [[LOOP]]
; CHECK: loop:
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[BASE]], [[ENTRY:%.*]] ], [ null, [[FAIL]] ], [ [[GEP:%.*]], [[IF_THEN:%.*]] ]
-; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[AND]], [[ENTRY]] ], [ 0, [[FAIL]] ], [ [[INC:%.*]], [[IF_THEN]] ]
+; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[AND]], [[ENTRY]] ], [ 0, [[FAIL]] ], [ [[INC:%.*]], [[IF_THEN]] ]
; CHECK-NEXT: [[UNDEF:%.*]] = icmp eq ptr [[PTR]], undef
; CHECK-NEXT: br i1 [[UNDEF]], label [[EXIT:%.*]], label [[IF_THEN]]
; CHECK: if.then:
; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[PTR]], align 2
-; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IDX]], 1
-; CHECK-NEXT: [[GEP]] = getelementptr inbounds i16, ptr [[PTR]], i32 [[INC]]
+; CHECK-NEXT: [[INC]] = add nuw nsw i8 [[IDX]], 1
+; CHECK-NEXT: [[GEP]] = getelementptr inbounds i16, ptr [[PTR]], i8 [[INC]]
; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[GEP]], [[OTHER]]
; CHECK-NEXT: br i1 [[COND]], label [[EXIT]], label [[LOOP]]
; CHECK: exit:
More information about the llvm-commits
mailing list