[llvm] [IR][TRE] Support associative intrinsics (PR #74226)
Joshua Cao via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 3 15:46:42 PST 2023
================
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | FileCheck %s
+
+%struct.ListNode = type { i32, ptr }
+
+define noundef i32 @umin(ptr noundef readonly %a) {
+; CHECK-LABEL: define noundef i32 @umin
+; CHECK-SAME: (ptr noundef readonly [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
+; CHECK: tailrecurse:
+; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]
+; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null
+; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]
+; CHECK: common.ret6:
+; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umin.i32(i32 -1, i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]
+; CHECK: if.end:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1
+; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8
+; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umin.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: br label [[TAILRECURSE]]
+;
+entry:
+ %tobool.not = icmp eq ptr %a, null
+ br i1 %tobool.not, label %common.ret6, label %if.end
+
+common.ret6: ; preds = %entry, %if.end
+ %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -1, %entry ]
+ ret i32 %common.ret6.op
+
+if.end: ; preds = %entry
+ %0 = load i32, ptr %a
+ %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1
+ %1 = load ptr, ptr %next
+ %call = tail call noundef i32 @umin(ptr noundef %1)
+ %.sroa.speculated = tail call i32 @llvm.umin.i32(i32 %0, i32 %call)
+ br label %common.ret6
+}
+
+define noundef i32 @umax(ptr noundef readonly %a) {
+; CHECK-LABEL: define noundef i32 @umax
+; CHECK-SAME: (ptr noundef readonly [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
+; CHECK: tailrecurse:
+; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]
+; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null
+; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]
+; CHECK: common.ret6:
+; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umax.i32(i32 0, i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]
+; CHECK: if.end:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1
+; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8
+; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umax.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: br label [[TAILRECURSE]]
+;
+entry:
+ %tobool.not = icmp eq ptr %a, null
+ br i1 %tobool.not, label %common.ret6, label %if.end
+
+common.ret6: ; preds = %entry, %if.end
+ %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 0, %entry ]
+ ret i32 %common.ret6.op
+
+if.end: ; preds = %entry
+ %0 = load i32, ptr %a
+ %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1
+ %1 = load ptr, ptr %next
+ %call = tail call noundef i32 @umax(ptr noundef %1)
+ %.sroa.speculated = tail call i32 @llvm.umax.i32(i32 %0, i32 %call)
+ br label %common.ret6
+}
+
+define noundef i32 @smin(ptr noundef readonly %a) {
+; CHECK-LABEL: define noundef i32 @smin
+; CHECK-SAME: (ptr noundef readonly [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
+; CHECK: tailrecurse:
+; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]
+; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null
+; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]
+; CHECK: common.ret6:
+; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smin.i32(i32 2147483647, i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]
+; CHECK: if.end:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1
+; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8
+; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smin.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: br label [[TAILRECURSE]]
+;
+entry:
+ %tobool.not = icmp eq ptr %a, null
+ br i1 %tobool.not, label %common.ret6, label %if.end
+
+common.ret6: ; preds = %entry, %if.end
+ %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 2147483647, %entry ]
+ ret i32 %common.ret6.op
+
+if.end: ; preds = %entry
+ %0 = load i32, ptr %a
+ %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1
+ %1 = load ptr, ptr %next
+ %call = tail call noundef i32 @smin(ptr noundef %1)
+ %.sroa.speculated = tail call i32 @llvm.smin.i32(i32 %0, i32 %call)
+ br label %common.ret6
+}
+
+define noundef i32 @smax(ptr noundef readonly %a) {
+; CHECK-LABEL: define noundef i32 @smax
+; CHECK-SAME: (ptr noundef readonly [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
+; CHECK: tailrecurse:
+; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]
+; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null
+; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]
+; CHECK: common.ret6:
+; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smax.i32(i32 -2147483648, i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]
+; CHECK: if.end:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1
+; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8
+; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smax.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])
+; CHECK-NEXT: br label [[TAILRECURSE]]
+;
+entry:
+ %tobool.not = icmp eq ptr %a, null
+ br i1 %tobool.not, label %common.ret6, label %if.end
+
+common.ret6: ; preds = %entry, %if.end
+ %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -2147483648, %entry ]
+ ret i32 %common.ret6.op
+
+if.end: ; preds = %entry
+ %0 = load i32, ptr %a
+ %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1
+ %1 = load ptr, ptr %next
+ %call = tail call noundef i32 @smax(ptr noundef %1)
+ %.sroa.speculated = tail call i32 @llvm.smax.i32(i32 %0, i32 %call)
+ br label %common.ret6
+}
----------------
caojoshua wrote:
Added a test for saturating signed add
https://github.com/llvm/llvm-project/pull/74226
More information about the llvm-commits
mailing list